विंडोज पर एक बहुत बड़ी (800GB) टेक्स्ट फ़ाइल की सामग्री को सॉर्ट करें


25

मेरे पास प्रत्येक पंक्ति में एक शब्द के साथ एक पाठ फ़ाइल है, फ़ाइल का आकार 800GB है। मुझे वर्णानुक्रम में शब्दों को क्रमबद्ध करना होगा।

मैंने विंडोज सॉर्ट प्रोग्राम का उपयोग करके कोशिश की है :

sort.exe input.txt /o output.txt

जो त्रुटि देता है: सॉर्ट को पूरा करने के लिए पर्याप्त मुख्य मेमोरी नहीं है।

मेरे पास 32GB RAM है तो जब मैं 10GB मेमोरी का उपयोग करके सॉर्ट करने के लिए निर्दिष्ट करने का प्रयास करता हूं:

sort.exe input.txt /o output.txt /M 10000000

मुझे मिला:

चेतावनी: निर्दिष्ट मेमोरी का आकार उपलब्ध पेजिंग मेमोरी को कम किया जा रहा है।

इनपुट रिकॉर्ड अधिकतम लंबाई से अधिक है। अधिकतम बड़ा निर्दिष्ट करें।

मेरे विकल्प क्या हैं?



10
यह एक क्रॉस-पोस्ट नहीं है, मैं एक मशीन नहीं हूं इसलिए इसे पोस्ट करना और दूसरे को हटाना कुछ मिनट लगते हैं!
मैय्यन

3
भविष्य में समुदाय को आपके प्रश्न
रामहाउंड

4
लिनक्स के साथ, आप इस विधि को लागू कर सकते हैं । 100 एमबी की फाइलों के साथ, यह एक बड़ी समस्या नहीं होनी चाहिए।
एरिक डुमिनील

3
आप विंडोज के किस संस्करण का उपयोग कर रहे हैं? पुराने Windows Server 2012 R2 के साथ Sort.exe डिस्क पर एक अस्थायी फ़ाइल (एक आकार सीमा का दस्तावेजीकरण के बिना) के उपयोग के साथ बाहरी मर्ज करने में सक्षम होने का दावा करता है। अस्थायी फ़ाइल के लिए 800Gb के साथ डिस्क निर्दिष्ट करने के लिए / T का उपयोग करने का प्रयास करें। और "इनपुट रिकॉर्ड अधिकतम लंबाई से अधिक है" के बारे में संदेश अंतरिक्ष के लिए असंबंधित लगता है - / REC विकल्प को देखें और विचार करें कि आपकी लाइन टर्मिनेशन क्या है।
दाविदबक

जवाबों:


16

मेरे विकल्प क्या हैं?

फ्रीवेयर कमांड लाइन की कोशिश करें उपयोगिता सीएमएस सॉर्ट करें

यह कई अस्थायी फ़ाइलों का उपयोग करता है और फिर उन्हें अंत में विलय कर देता है।

CMsort एक इनपुट फ़ाइल का रिकॉर्ड पढ़ रहा है जब तक कि समायोजित मेमोरी नहीं पहुँच जाती है। फिर अभिलेखों को क्रमबद्ध किया जाता है और एक अस्थायी फाइल पर लिखा जाता है। यह तब तक दोहराया जाएगा जब तक सभी रिकॉर्ड संसाधित नहीं हो जाते। अंत में, सभी अस्थायी फ़ाइलों को आउटपुट फ़ाइल में मिला दिया जाता है। यदि उपलब्ध मेमोरी पर्याप्त है, तो कोई अस्थायी फ़ाइलें नहीं लिखी जाती हैं और विलय की आवश्यकता नहीं होती है।

एक उपयोगकर्ता रिपोर्ट करता है कि उसने 130,000,000 बाइट्स की एक फ़ाइल को छांटा है।

यदि आप स्वयं कुछ कोड को ट्वीक करना चाहते हैं, तो सॉर्टिंग विशाल टेक्स्ट फाइलें भी हैं - कोडप्रोजेक्ट - "टेक्स्ट फाइलों के आकार में छंटाई लाइनों का एल्गोरिथ्म जिसमें उपलब्ध मेमोरी से अधिक है"


26
वाह, 130 मेगाबाइट !!! +1
डेविड फ़ॉस्टर

3
@DavidPostill क्या आप सुनिश्चित हैं कि विंडोज़ के लिए कोर्यूटिल्स से सॉर्ट करना अधिक कुशल नहीं है ( --parallelविकल्प यदि आपके पास एक से अधिक कोर हैं)?
हस्त्तूर

23

एक अन्य विकल्प फ़ाइल को डेटाबेस में लोड करना है। उदाहरण के लिए MySQL और MySQL कार्यक्षेत्र।
डेटाबेस बड़ी फ़ाइलों के साथ काम करने के लिए एकदम सही उम्मीदवार हैं

यदि आपकी इनपुट फ़ाइल में नई लाइन द्वारा अलग किए गए शब्द हैं तो यह कठिन नहीं होना चाहिए।

डेटाबेस और MySQL कार्यक्षेत्र को स्थापित करने के बाद आपको यही करना होगा।
पहले स्कीमा बनाएं (यह शब्द लंबे समय तक नहीं रहेगा कि 255 अक्षर हालांकि आप तर्क मान बढ़ाकर इसे बदल सकते हैं)। पहला कॉलम "idwords" एक प्राथमिक कुंजी है।

CREATE SCHEMA `tmp` ;

CREATE TABLE `tmp`.`words` (
  `idwords` INT NOT NULL AUTO_INCREMENT,
  `mywords` VARCHAR(255) NULL,
  PRIMARY KEY (`idwords`));

दूसरा डेटा आयात करें: ईजी यह सभी शब्दों को तालिका में आयात करेगा (इस चरण को पूरा होने में कुछ समय लग सकता है। मेरी सलाह होगी कि पहले एक छोटे शब्द फ़ाइल के साथ एक परीक्षण चलाएं और एक बार जब आप सुनिश्चित कर लें कि प्रारूप समान है बड़ा एक (तालिका को छोटा करें .. IE इसे साफ़ करें और पूरा डेटा सेट लोड करें)।

LOAD DATA LOCAL INFILE "C:\\words.txt" INTO TABLE tmp.words
LINES TERMINATED BY '\r\n'
(mywords);


यह लिंक लोड के लिए प्रारूप सही होने में मदद कर सकता है। https://dev.mysql.com/doc/refman/5.7/en/load-data.html
ईजी यदि आप पहली पंक्ति को छोड़ना चाहते हैं, तो आप निम्नलिखित कार्य करेंगे।

LOAD DATA LOCAL INFILE "H:\\words.txt" INTO TABLE tmp.words
-- FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(mywords);

अंत में सॉर्ट की गई फाइल को सेव करें। आपको पीसी पर निर्भर करते हुए इसमें कुछ समय लग सकता है।

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
INTO OUTFILE 'C:\\sorted_words.csv';

आप जैसा चाहें वैसा डाटा सर्च भी कर सकते हैं। ईजी यह आपको आरोही क्रम में पहले 50 शब्द देगा (0 या पहले शब्द से शुरू)।

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
LIMIT 0, 50 ;

सौभाग्य
पीट


2
यह है काफी मार्जिन से सही जवाब।
मंकीज़ियस

1
यह दृष्टिकोण निश्चित रूप से अधिक लचीला होगा, खासकर अगर आपको पता है कि आपको एक अलग क्रम के साथ सॉर्ट को फिर से चलाने की आवश्यकता है, उदाहरण के लिए।
बारबेक्यू

मुझे परवाह नहीं है कि MySQL , MariaDB या किसी अन्य DBMS की आपकी आवृत्ति कितनी तेज़ है, यह उसी मशीन पर चल रहे SQLite के सम्मिलित प्रदर्शन के करीब कहीं भी आने वाला नहीं है । SQLite के रूप में उपवास के साथ भी डेटा की यह मात्रा बहुत अधिक है (और धीमा) संसाधित करने के लिए (मुझे विश्वास है कि मैंने पहली बार कोशिश की थी!) तो सबसे अच्छा समाधान डुप्लिकेट को पहले सॉर्ट करना और निकालना है फिर SQLite जैसे DB में सम्मिलित करें । तो जबकि यह समाधान कुछ मामलों के लिए मान्य हो सकता है, यह निश्चित रूप से वह नहीं है जो मैं करने की कोशिश कर रहा हूं। वैसे भी इस पोस्ट करने के लिए समय निकालने के लिए धन्यवाद।
मैयना

द्वारा आदेश mywordsहमेशा के लिए ले जाएगा। यहां तक ​​कि LIMIT, यह पूरी तरह से तब तक ले जाएगा, क्योंकि MySQL को हर एक मूल्य से गुजरना होगा mywordsऔर उन्हें ऑर्डर करना होगा। इसे ठीक करने के लिए, आपको निम्नलिखित काम करने होंगे LOAD DATA। इसमें एक इंडेक्स जोड़ें mywords। अब आप उस कॉलम के द्वारा ऑर्डर कर सकते हैं, न कि इसे सहस्राब्दी तक ले सकते हैं। और यह है डेटा लोड करने के बाद के बजाय बार जब आप तालिका बनाई (बहुत तेजी से डेटा लोड) में सूचकांक से जोड़ने के लिए बेहतर है।
ब्यूटेल बटुक

7

sort

कई एल्गोरिदम का उपयोग क्रमबद्ध और क्रमबद्ध फ़ाइलों के लिए किया जाता है [ 1 ]
चूंकि वे सभी एल्गोरिदम पहले से ही लागू हैं, इसलिए पहले से ही परीक्षण किए गए प्रोग्राम को चुनें।

में coreutils (लिनक्स से लेकिन खिड़कियों के लिए उपलब्ध भी [ 2 ] ), यह मौजूद है sortआदेश मल्टी कोर प्रोसेसर के तहत समानांतर में चलाने के लिए सक्षम: आम तौर पर यह पर्याप्त है।

यदि आपकी फ़ाइल है इतनी बड़ी आप प्रसंस्करण बंटवारे (मदद कर सकते हैं split -l), कुछ मात्रा में फ़ाइल, संभवतः समानांतर विकल्प (का उपयोग करते हुए --parallel), और परिणामस्वरूप छँटाई आदेश दिया-मात्रा के साथ -mविकल्प ( मर्ज तरह )।
इसे करने के कई तरीकों में से एक यहाँ समझाया गया है (स्प्लिट फाइल, ऑर्डर सिंगल चंक्स, मर्ज ऑर्डर चंक्स, डिलीट टेम्प फाइल्स)।

टिप्पणियाँ:

  • विंडोज़ 10 में लिनक्स के लिए तथाकथित विंडोज सबसिस्टम मौजूद है जिसमें सभी लिनक्स उदाहरण अधिक प्राकृतिक प्रतीत होंगे।
  • अलग-अलग एल्गोरिदम के साथ सॉर्ट करने पर अलग-अलग निष्पादन समय होता है जो कि डेटा प्रविष्टियों की संख्या के प्रकार के रूप में सॉर्ट किया जाता है (O (n m ), O (nlogn) ...)।
  • एल्गोरिथ्म की दक्षता उस आदेश पर निर्भर करती है जो मूल फ़ाइल में पहले से मौजूद है।
    (उदाहरण के लिए एक बुलबुला सॉर्ट पहले से ही ऑर्डर की गई फ़ाइल के लिए सबसे तेज़ एल्गोरिथम है - बिल्कुल एन -, लेकिन यह अन्य मामलों में कुशल नहीं है)।

2

पीटर एच को वैकल्पिक समाधान की पेशकश करने के लिए, एक प्रोग्राम क्यू है जो एसक्यूएल स्टाइल कमांड को टेक्स्ट फाइलों के खिलाफ अनुमति देता है। SQL कार्यक्षेत्र को स्थापित करने या तालिकाओं को स्थापित करने की आवश्यकता के बिना नीचे दी गई कमांड समान होगी (फ़ाइल के समान कमांड प्रॉम्प्ट से फ़ाइल में चलाएं)।

q "select * from words.txt order by c1"

c1 कॉलम 1 के लिए आशुलिपि है।

आप डुप्लिकेट शब्दों को बाहर कर सकते हैं

q "select distinct c1 from words.txt order by c1"

और आउटपुट को दूसरी फ़ाइल में भेजें

q "select distinct c1 from words.txt order by c1" > sorted.txt

किसी भी विचार है कि क्या यह एक 800 टमटम फ़ाइल के साथ सामना करेगा?
कच्चे

1
मैं 100% सुनिश्चित नहीं हूं - मैंने 1200 लाइन फ़ाइल (9KB) के साथ उपरोक्त परीक्षण किया। डेवलपर्स पृष्ठ में एक "सीमाएं" पृष्ठ होता है जो अधिकतम फ़ाइल आकार के बारे में कुछ भी उल्लेख नहीं करता है। एक बड़ी फ़ाइल अभी भी स्मृति समस्या के खिलाफ आ सकती है।
ब्रायन

3
क्ष इस राशि संसाधित नहीं कर सकता का डेटा याद रखें कि क्ष का उपयोग करता है SQLite दृश्य के पीछे अगर मैं लोड नहीं कर सका डेटा करने के लिए प्रत्यक्ष SQLite क्या आपको लगता है बनाता है क्ष कर सकते हैं?
मैयना

2

यदि प्रत्येक पंक्ति के शब्द एक सीमित शब्दावली (जैसे अंग्रेजी) से हैं, तो आप ट्रीपेज और रिकॉर्डिंग काउंट (जहां मी अद्वितीय मानों की संख्या है) का उपयोग करके सूची को O (n + m लॉग मी) समय में सॉर्ट कर सकते हैं।

अन्यथा आप जावा लाइब्रेरी को बड़े-सॉर्टर का उपयोग कर सकते हैं । यह इंटरमीडिएट फ़ाइलों के लिए इनपुट को विभाजित करता है और उन्हें कुशलतापूर्वक (समग्र O (nlogn)) मर्ज करता है। आपकी फ़ाइल को इस तरह दिखता है:

Sorter.serializerTextUtf8()
      .input(inputFile)
      .output(outputFile)
      .loggerStdOut() // display some progress
      .sort();

मैंने यादृच्छिक रूप से उत्पन्न 16 वर्ण शब्दों के साथ एक 1.7GB फ़ाइल (100 मीटर लाइन्स) बनाई और इसे 142 में ऊपर की तरह क्रमबद्ध किया और मैं जिस विधि का उपयोग कर रहा हूं, उस पर O (n लॉग एन) कम्प्यूटेशनल जटिलता के आधार पर मैंने 16 वर्ण शब्दों के 800GB का अनुमान लगाया है। SSD के साथ अपने i5 2.3GHz लैपटॉप पर सिंगल-थ्रेडेड सॉर्ट करने के लिए लगभग 24 घंटे का समय लें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.