किसी बड़ी फ़ाइल (80GB) को तेजी से बढ़ाने का कोई तरीका?


113
 grep -i -A 5 -B 5 'db_pd.Clients'  eightygigsfile.sql

यह काफी शक्तिशाली लिनक्स सर्वर पर एक घंटे से चल रहा है जो अन्यथा अतिभारित नहीं है। Grep का कोई विकल्प? मेरे सिंटैक्स के बारे में कुछ भी जिसे बेहतर बनाया जा सकता है, (उदाहरण के लिए, fgrep बेहतर?)

फ़ाइल वास्तव में एक निर्देशिका में है जो एक माउंट के साथ दूसरे सर्वर पर साझा की जाती है लेकिन वास्तविक डिस्कस्पेस स्थानीय है ताकि कोई अंतर न हो?

grep 93% CPU तक हड़प रहा है


8
आपके स्थान के आधार पर, -iस्विच प्रक्रिया को धीमा कर सकता है, बिना -iया उसके साथ प्रयास करें LC_ALL=C grep ...। इसके अलावा, यदि आप केवल एक निश्चित स्ट्रिंग के लिए पकड़ रहे हैं, का उपयोग करें grep -F
थॉर

5
@Dogbane का उपयोग कर उल्लेख किया है LC_ALL = सी के साथ चर fgrep अपने search.I में तेजी लाने के कर सकते हैं कुछ परीक्षण किया था और एक को प्राप्त करने में सक्षम था 1400% प्रदर्शन वृद्धि हुई है और एक विस्तृत लेख क्यों यह मेरा है लिखा गति ग्रेप ऊपर पोस्ट
JacobN

मैं उत्सुक हूँ - क्या फ़ाइल आकार में 80GB है? मैं यह सोचना चाहता हूं कि जब कोई फ़ाइल इतनी बड़ी हो जाती है, तो एक बेहतर भंडारण रणनीति हो सकती है (जैसे लॉग फ़ाइलों को घुमाना, या अलग-अलग फ़ाइलों और फ़ोल्डरों में श्रेणीबद्ध रूप से वर्गीकृत करना)। इसके अलावा, यदि परिवर्तन केवल फ़ाइल के कुछ स्थानों में होते हैं (उदाहरण के अंत में), तो बस पिछले अनुभाग से कुछ grep परिणाम संग्रहीत करें जो परिवर्तित नहीं होते हैं और मूल फ़ाइल को grepping करने के बजाय संग्रहीत परिणाम फ़ाइल को grep करते हैं।
श्रीधर सरनोबत

मैं github.com/google/codesearch पर बस गया - दोनों अनुक्रमण और खोज बिजली से तेज़ हैं (गो में लिखे गए)। cindex .अपने वर्तमान फ़ोल्डर को इंडेक्स करने के लिए, फिर csearch db_pd.Clients
2

1
यदि आपकी फ़ाइल अनुक्रमित या सॉर्ट की गई थी, तो इसे बहुत तेज़ी से बनाया जा सकता है । हर पंक्ति की खोज करना परिभाषा के अनुसार O (n) है, जबकि एक सॉर्ट की गई फ़ाइल को द्विभाजित करके खोजा जा सकता है - जिस बिंदु पर आप अपने 80 जीबी को खोजने के लिए एक दूसरे के तहत बात कर रहे होंगे (इसलिए क्यों एक 80 जीबी अनुक्रमित डेटाबेस को बिल्कुल भी समय नहीं लगता है एक सरल चयन के लिए, जबकि आपका grep लेता है ... ठीक है, जब तक यह लेता है)।
चार्ल्स डफी

जवाबों:


148

यहाँ कुछ विकल्प दिए गए हैं:

1) LC_ALL=CUTF-8 के बजाय C लोकेल का उपयोग करने के लिए अपने grep कमांड को उपसर्ग करें ।

2) उपयोग करें fgrepक्योंकि आप एक निश्चित स्ट्रिंग की खोज कर रहे हैं, न कि एक नियमित अभिव्यक्ति।

3) -iविकल्प को हटा दें , अगर आपको इसकी आवश्यकता नहीं है।

तो आपकी आज्ञा बन जाती है:

LC_ALL=C fgrep -A 5 -B 5 'db_pd.Clients' eightygigsfile.sql

यदि आप अपनी फाइल को RAM डिस्क पर कॉपी करते हैं तो यह भी तेज होगा।


5
धन्यवाद के एक क्रम से यह बहुत जल्दी था। BTW मैंने लाइन नंबर प्राप्त करने के लिए जोड़ा। मैच के बाद बाहर निकलने के लिए भी शायद -m
zzapper

5
वाह धन्यवाद इतना @dogbane महान टिप! इससे मुझे पता लगाने के लिए एक शोध सुरंग का नेतृत्व किया कि LC_ALL = C ने grep को गति क्यों दी और यह एक बहुत ही ज्ञानवर्धक अनुभव था!
याकूब

7
कुछ लोग (मुझे नहीं) grep -Fसे अधिक पसंद करते हैंfgrep
वाल्टर ट्रॉस

2
मेरी समझ यह है कि LANG=C(के बजाय LC_ALL=C) पर्याप्त है, और टाइप करना आसान है।
वाल्टर ट्रॉस

2
@ एड्रियन fgrepलिखने का एक और तरीका है grep -F, जैसा man fgrepकि आप बताएंगे। कुछ संस्करणों का यह manभी कहना है कि पूर्व को बाद के लिए पदावनत किया जाता है, लेकिन छोटा रूप मरने के लिए बहुत सुविधाजनक है।
वाल्टर ट्रॉस

36

यदि आपके पास एक मल्टीकोर सीपीयू है, तो मैं वास्तव में जीएनयू समानांतर की सिफारिश करूंगा । समानांतर उपयोग में एक बड़ी फ़ाइल प्राप्त करने के लिए:

< eightygigsfile.sql parallel --pipe grep -i -C 5 'db_pd.Clients'

आपके डिस्क और सीपीयू के आधार पर बड़े ब्लॉक पढ़ने में तेज़ हो सकता है:

< eightygigsfile.sql parallel --pipe --block 10M grep -i -C 5 'db_pd.Clients'

यह आप से सवाल पूरी तरह से स्पष्ट नहीं है, लेकिन grepशामिल करने के लिए अन्य विकल्प :

  • -iझंडे को गिराना।
  • -Fएक निश्चित स्ट्रिंग के लिए ध्वज का उपयोग करना
  • एनएलएस को अक्षम करना LANG=C
  • -mध्वज के साथ अधिकतम मिलान सेट करना ।

2
यदि यह एक वास्तविक फ़ाइल है, तो --pipepartइसके बजाय का उपयोग करें --pipe। यह बहुत तेज है।
ओले तांगे

इस उपयोग का समर्थन नहीं करने वाले पैटर्न में स्थान शामिल है, हमें इस तरह का उपयोग करने की आवश्यकता है: समानांतर --pipe --block 10M "/ usr / bin / grep -F -C5 -e 'एनिमल केयर एंड पेट्स'"
zw963

<समानांतर कमान से पहले के चरित्र का क्या अर्थ है ?
एस्कॉर्टेगनो

1
@elcortegano: यह वही है जिसे I / O पुनर्निर्देशन कहा जाता है । मूल रूप से, यह निम्न फ़ाइल नाम से इनपुट पढ़ता है। इसी तरह cat file.sql | parallel ...लेकिन UUOC से बचा जाता है । जीएनयू समानांतर में एक फ़ाइल का उपयोग करके इनपुट पढ़ने का एक तरीका भी है parallel ... :::: file.sql। HTH।
स्टीव

10

कुछ तुच्छ सुधार:

  • -I विकल्प निकालें, यदि आप कर सकते हैं, तो असंवेदनशील मामला काफी धीमा है।

  • .द्वारा प्रतिस्थापित करें\.

    एक एकल बिंदु किसी भी वर्ण से मेल करने के लिए रेगेक्स प्रतीक है, जो धीमा भी है


3

हमले की दो लाइनें:

  • क्या आप सुनिश्चित हैं, आपको इसकी आवश्यकता है -i, या क्या आप इससे छुटकारा पाने की संभावना को कम करते हैं?
  • क्या आपके पास खेलने के लिए अधिक कोर है? grepसिंगल-थ्रेडेड है, इसलिए हो सकता है कि आप अलग-अलग ऑफ़सेट्स में उनमें से अधिक शुरू करना चाहें।

1
< eightygigsfile.sql parallel -k -j120% -n10 -m grep -F -i -C 5 'db_pd.Clients'  

यदि आपको कई स्ट्रिंग्स की खोज करने की आवश्यकता है, तो grep -f strings.txt एक टन समय बचाता है। उपरोक्त किसी चीज़ का अनुवाद है जिसका मैं वर्तमान में परीक्षण कर रहा हूँ। -j और -n विकल्प मान मेरे उपयोग के मामले के लिए सबसे अच्छा काम करता था। -F grep ने भी एक बड़ा बदलाव किया।

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