एक फ़ोल्डर में लाखों (छोटी) टेक्स्ट फाइलें


15

हम एक लिनक्स फाइल सिस्टम में लाखों पाठ फ़ाइलों को संग्रहीत करना चाहते हैं, जिसका उद्देश्य सेवा के रूप में मनमाना संग्रह करना और सेवा देना है। हमने कुंजी / मूल्य डेटाबेस की तरह अन्य समाधानों की कोशिश की है, लेकिन समवर्ती और समानता के लिए हमारी आवश्यकताएं मूल फाइल सिस्टम का सबसे अच्छा विकल्प का उपयोग करती हैं।

सबसे सरल तरीका एक फ़ोल्डर में सभी फ़ाइलों को संग्रहीत करना है:

$ ls text_files/
1.txt
2.txt
3.txt

जो एक EXT4 फ़ाइल सिस्टम पर संभव होना चाहिए , जिसमें किसी फ़ोल्डर में फ़ाइलों की संख्या की कोई सीमा नहीं है।

दो FS प्रक्रियाएं होंगी:

  1. वेब स्क्रैप से पाठ फ़ाइल लिखें (फ़ोल्डर में फ़ाइलों की संख्या से प्रभावित नहीं होना चाहिए)।
  2. जिपं चयनित फाइल, फाइलनाम की सूची द्वारा दी गई।

मेरा सवाल यह है कि क्या एक फोल्डर में दस मिलियन तक फाइलें जमा हो जाएंगी, ऊपर के ऑपरेशनों या सामान्य सिस्टम के प्रदर्शन को प्रभावित करती हैं, किसी भी फाइल में रहने के लिए सबफ़ोल्डर्स का पेड़ बनाने से अलग?


4
संबंधित: एमवी के दौरान "अंतरिक्ष में डिवाइस पर कोई जगह नहीं छोड़ी गई" त्रुटियों को कैसे ठीक करें जब डिवाइस में बहुत अधिक स्थान होता है । उपयोग करना dir_index, जो अक्सर डिफ़ॉल्ट रूप से सक्षम होता है, लुकअप को गति देगा लेकिन प्रति निर्देशिका फ़ाइलों की संख्या को सीमित कर सकता है।
मार्क प्लॉटनिक

वर्चुअल मशीन पर इसे जल्दी से आज़मा कर क्यों न देखें कि यह कैसा है? बैश के साथ यह एक फ़ोल्डर है जिसमें एक लाख पाठ फ़ाइलों के साथ यादृच्छिक वर्णों के साथ एक फ़ोल्डर को आबाद करना है। मुझे ऐसा लगता है कि यहाँ जो कुछ भी आप सीखेंगे, उसके अलावा आपको वास्तव में उपयोगी जानकारी मिलेगी।
यहोशू

2
@JoshuaD: यदि आप इसे एक ही बार में सभी को ताज़ा FS पर पॉप्युलेट करते हैं, तो आपको डिस्क पर सभी इनोड्स सन्निहित होने की संभावना है, इसलिए ls -lया कुछ और जो statनिर्देशिका में हर इनोड में है (जैसे bashग्लोबिंग / टैब पूरा करना) कृत्रिम रूप से तेज़ होगा। कुछ पहनने और आंसू के बाद (कुछ फ़ाइलों को हटा दें, कुछ नए लिखें)। ext4 XFS की तुलना में बेहतर कर सकता है, क्योंकि XFS डायनामिक रूप से इनोड्स बनाम डेटा के लिए स्थान आवंटित करता है, इसलिए आप इनोड्स को अधिक बिखरे हुए के साथ समाप्त कर सकते हैं, मुझे लगता है। (लेकिन यह बहुत कम विस्तृत ज्ञान के आधार पर एक शुद्ध अनुमान है; मैंने मुश्किल से ext4 का उपयोग किया है)। abc/def/मातहतों के साथ जाओ ।
पीटर कॉर्ड्स

हाँ, मुझे नहीं लगता कि मैंने जो परीक्षण सुझाया है वह ओपी को "यह काम करेगा" बताने में सक्षम होगा, लेकिन यह निश्चित रूप से उसे जल्दी से बता सकता है "यह काम नहीं करेगा", जो उपयोगी है।
यहोशू

1
लेकिन संगामिति और समानांतरता के लिए हमारी आवश्यकताएं मूल फाइलसिस्टम का उपयोग करते हुए सबसे अच्छा विकल्प है कि आपने क्या प्रयास किया? ऑफ़हैंड, मुझे लगता है कि MySQL और जावा सर्वलेट जैसे लोअर-एंड RDBMS भी उड़ने के साथ ज़िप फाइल बनाते हैंZipOutputStream ही किसी भी मुफ्त लिनक्स देशी फाइल सिस्टम को हरा देंगे - मुझे संदेह है कि आप आईबीएम के GPFS के लिए भुगतान करना चाहते हैं। JDBC परिणाम सेट करने और उस ज़िप स्ट्रीम को बनाने के लिए लूप शायद जावा कोड की 6-8 पंक्तियाँ हैं।
एंड्रयू हेनले

जवाबों:


10

lsआदेश, या यहाँ तक टैब-पूर्ण या खोल से वाइल्डकार्ड विस्तार, सामान्य रूप से अल्फान्यूमेरिक क्रम में उनके परिणाम पेश करेंगे। इसके लिए संपूर्ण निर्देशिका सूची को पढ़ना और उसे क्रमबद्ध करना आवश्यक है। एक एकल निर्देशिका में दस मिलियन फ़ाइलों के साथ, यह छंटनी ऑपरेशन एक गैर-नगण्य राशि लेगा।

यदि आप TAB- पूरा करने के आग्रह का विरोध कर सकते हैं और उदाहरण के लिए, पूर्ण रूप से ज़िपित होने वाली फ़ाइलों के नाम लिखें, तो कोई समस्या नहीं होनी चाहिए।

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

यह आपके वाइल्डकार्ड संचालन को findकमांड का उपयोग करके हल किया जा सकता है :

find <directory> -name '<wildcard expression>' -exec <command> {} \+

या एक समान वाक्यविन्यास जब भी संभव हो। find ... -exec ... \+स्वचालित रूप से खाते में अधिकतम आदेश पंक्ति लंबाई ले जाएगा, और कई बार के रूप में कमांड निष्पादित करेंगे के रूप में आवश्यक है, जबकि प्रत्येक कमांड लाइन करने के लिए फ़ाइल नाम की अधिकतम राशि फिटिंग।


आधुनिक फाइलसिस्टम निर्देशिका प्रविष्टियों को रखने के लिए बी, बी + या इसी तरह के पेड़ों का उपयोग करते हैं। en.wikipedia.org/wiki/HTree
DIMM

4
हां ... लेकिन यदि शेल या lsकमांड को यह पता नहीं चलेगा कि डायरेक्टरी लिस्टिंग पहले से सॉर्ट की गई है, तो वे वैसे भी सॉर्टिंग एल्गोरिदम को चलाने के लिए समय लेने वाले हैं। और इसके अलावा, उपयोगकर्ता स्थान एक स्थानीयकृत सॉर्टिंग ऑर्डर (LC_COLLATE) का उपयोग कर सकता है जो कि फाइल सिस्टम आंतरिक रूप से क्या कर सकता है, उससे अलग हो सकता है।
टेल्कोएम

17

यह एक राय-आधारित प्रश्न / उत्तर के करीब है, लेकिन मैं अपनी राय के साथ कुछ तथ्य प्रदान करने का प्रयास करूंगा।

  1. यदि आपके पास एक फ़ोल्डर में बहुत बड़ी संख्या में फाइलें हैं, तो कोई भी शेल-आधारित ऑपरेशन जो उन्हें गणना करने की कोशिश करता है (उदाहरण के लिए mv * /somewhere/else) वाइल्डकार्ड को सफलतापूर्वक विस्तारित करने में विफल हो सकता है, या परिणाम का उपयोग करने के लिए बहुत बड़ा हो सकता है।
  2. ls फ़ाइलों की एक छोटी संख्या की तुलना में बड़ी संख्या में फ़ाइलों की गणना करने में अधिक समय लगेगा।
  3. फाइलसिस्टम एक डायरेक्टरी में लाखों फाइलों को संभालने में सक्षम होगा, लेकिन लोग शायद संघर्ष करेंगे।

एक सिफारिश फाइलनाम को दो, तीन या चार वर्ण विखंडू में विभाजित करने और उपनिर्देशिका के रूप में उपयोग करने के लिए है। उदाहरण के लिए, के somefilename.txtरूप में संग्रहीत किया जा सकता है som/efi/somefilename.txt। यदि आप संख्यात्मक नाम का उपयोग कर रहे हैं तो बाएं से दाएं के बजाय दाएं से बाएं विभाजित करें ताकि अधिक समान वितरण हो। उदाहरण के लिए के 12345.txtरूप में संग्रहीत किया जा सकता है 345/12/12345.txt

के बराबर का उपयोग कर सकते हैं zip -j zipfile.zip path1/file1 path2/file2 ... ज़िप फ़ाइल में मध्यवर्ती उपनिर्देशिका पथों से बचने लिए ।

यदि आप एक वेबसर्वर से इन फ़ाइलों की सेवा कर रहे हैं (मुझे पूरी तरह से यकीन नहीं है कि क्या यह प्रासंगिक है) Apache2 में नियमों को फिर से लिखने के साथ एक आभासी निर्देशिका के पक्ष में इस संरचना को छिपाने के लिए तुच्छ है। मुझे लगता है कि Nginx के लिए भी यही सच है।


*जब तक आप स्मृति से बाहर चलाने के विस्तार सफल होगा, लेकिन जब तक आप (लिनक्स पर) stacksize सीमा को बढ़ा या एक खोल जहां का उपयोग mvbuiltin है या निर्मित किया जा सकता है (ksh93, zsh), execve()सिस्टम कॉल एक E2BIG त्रुटि के साथ विफल हो सकता है।
स्टीफन चेज़लस

@ StéphaneChazelas हाँ ठीक है, शब्दों की मेरी पसंद बेहतर हो सकती है, लेकिन उपयोगकर्ता के लिए शुद्ध प्रभाव बहुत अधिक है। मैं देखूंगा कि क्या मैं जटिलता में घिरे बिना शब्दों को थोड़ा बदल सकता हूं।
रोएमा

बस उत्सुक है कि आप उस ज़िप फ़ाइल को कैसे अनप्लग करेंगे, यदि आप उस पर इंटरमीडिएट उपनिर्देशिका पथों को शामिल करने से बचते हैं, बिना चर्चा किए मुद्दों में?
ऑक्टोपस

1
@ ओक्टोपस ने कहा कि ज़िप फ़ाइल में " चयनित फ़ाइल, फ़ाइलनाम की सूची द्वारा दी गई " होगी।
रोमीमा

मैं zip -j - ...ग्राहक के नेटवर्क कनेक्शन पर सीधे आउटपुट स्ट्रीम का उपयोग और पाइपिंग करने की सलाह दूंगा zip -j zipfile.zip ...। डिस्क के लिए एक वास्तविक ज़िपफिल लिखने का मतलब है कि डेटा पथ डिस्क से पढ़ा जाता है-> सेक-> डिस्क से लिखें-> डिस्क से पढ़ें-> क्लाइंट को भेजें। यह डिस्क से पढ़ने के लिए आपकी डिस्क IO आवश्यकताओं को तिगुना करने के लिए हो सकता है-> सेक-> क्लाइंट को भेजें।
एंड्रयू हेनले

5

मैं एक वेबसाइट चलाता हूं जो फिल्मों, टीवी और वीडियो गेम के लिए एक डेटाबेस संभालती है। इनमें से प्रत्येक के लिए टीवी के साथ कई चित्र हैं जिनमें प्रति शो दर्जनों चित्र हैं (यानी एपिसोड स्नैपशॉट आदि)।

बहुत सारी इमेज फाइल होने के कारण अंत होता है। कहीं 250,000+ रेंज में। ये सभी एक माउंटेड ब्लॉक स्टोरेज डिवाइस में स्टोर किए जाते हैं जहां पहुंच का समय उचित होता है।

छवियों को संग्रहीत करने का मेरा पहला प्रयास एकल फ़ोल्डर में था /mnt/images/UUID.jpg

मैं निम्नलिखित चुनौतियों में भाग गया।

  • lsएक रिमोट टर्मिनल के माध्यम से बस लटका होगा। यह प्रक्रिया ज़ोंबी हो CTRL+Cजाएगी और इसे नहीं तोड़ेगी।
  • इससे पहले कि मैं उस बिंदु तक पहुंचता हूं कोई भी lsकमांड आउटपुट बफर को जल्दी से भर CTRL+Cदेगा और अंतहीन स्क्रॉलिंग को बंद नहीं करेगा।
  • एक एकल फ़ोल्डर से 250,000 फ़ाइलों को ज़िप करने में लगभग 2 घंटे लगे। आपको टर्मिनल से अलग किए गए ज़िप कमांड को चलाना होगा अन्यथा कनेक्शन में किसी भी रुकावट का मतलब है कि आपको फिर से शुरू करना होगा।
  • मैं Windows पर ज़िप फ़ाइल का उपयोग करने का प्रयास नहीं करूंगा।
  • फोल्डर जल्दी से नो इन्सान ज़ोन बन गया ।

मैंने पथ बनाने के लिए निर्माण समय का उपयोग करके सबफ़ोल्डर्स में फ़ाइलों को संग्रहीत करने के लिए समाप्त कर दिया। इस तरह के रूप में /mnt/images/YYYY/MM/DD/UUID.jpg। इसने उपरोक्त सभी समस्याओं का समाधान किया, और मुझे ज़िप फ़ाइलों को बनाने की अनुमति दी, जिन्होंने एक तिथि को लक्षित किया।

यदि आपके पास एक फ़ाइल के लिए एकमात्र पहचानकर्ता एक संख्यात्मक संख्या है, और ये संख्याएँ क्रम से चलती हैं। क्यों नहीं उन्हें समूह द्वारा 100000, 10000और 1000

उदाहरण के लिए, यदि आपके पास 384295.txtपथ नाम की एक फ़ाइल होगी:

/mnt/file/300000/80000/4000/295.txt

यदि आप जानते हैं कि आप कुछ मिलियन तक पहुँचेंगे। 01,000,000 के लिए उपसर्गों का उपयोग करें

/mnt/file/000000/300000/80000/4000/295.txt

1

वेब स्क्रैप से पाठ फ़ाइल लिखें (फ़ोल्डर में फ़ाइलों की संख्या से प्रभावित नहीं होना चाहिए)।

एक नई फ़ाइल बनाने के लिए नई निर्देशिका प्रविष्टि के लिए पर्याप्त खाली स्थान की तलाश करने वाली निर्देशिका फ़ाइल को स्कैन करने की आवश्यकता होती है। यदि कोई स्थान स्थित नहीं है जो नई निर्देशिका प्रविष्टि को संग्रहीत करने के लिए पर्याप्त बड़ा है, तो इसे निर्देशिका फ़ाइल के अंत में रखा जाएगा। जैसे-जैसे किसी निर्देशिका में फ़ाइलों की संख्या बढ़ती है, वैसे-वैसे निर्देशिका को स्कैन करने का समय भी बढ़ता जाता है।

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

जिपं चयनित फाइल, फाइलनाम की सूची द्वारा दी गई।

यह भी लाखों फ़ाइलों के साथ एक निर्देशिका में अतिरिक्त समय की आवश्यकता है। फ़ाइल-सिस्टम में हैशेड निर्देशिका प्रविष्टियों (जैसे EXT4) के साथ, यह अंतर न्यूनतम है।

एक फ़ोल्डर में दस मिलियन फ़ाइलों तक भंडारण करने से उपरोक्त संचालन, या सामान्य प्रणाली के प्रदर्शन को प्रभावित किया जा सकता है, फाइलों में रहने के लिए सबफ़ोल्डर्स के पेड़ बनाने की तुलना में किसी भी तरह से अलग?

सबफ़ोल्डर्स के एक पेड़ में उपरोक्त प्रदर्शन कमियां नहीं हैं। इसके अलावा, यदि अंतर्निहित फ़ाइल-सिस्टम को हैशेड फ़ाइल नामों में नहीं बदला जाता है, तो ट्री कार्यप्रणाली अभी भी अच्छी तरह से काम करेगी।


1

सबसे पहले: 'ls' को 'ls -U' के साथ सॉर्ट करने से रोकें, हो सकता है कि अपने ~ / bashrc को 'alias ls = "ls -U' 'या इसी तरह के अपडेट करें।

अपनी बड़ी फ़ाइलसेट के लिए, आप इसे इस तरह आज़मा सकते हैं:

  • परीक्षण फ़ाइलों का एक सेट बनाएँ

  • देखें कि क्या कई फ़ाइल नाम समस्याओं का कारण बनते हैं

  • समस्याओं से बचने के लिए xipgs parmeter-batching और zip के फ़ाइलों को जोड़ने के लिए (डिफ़ॉल्ट) व्यवहार का उपयोग करें।

यह अच्छी तरह से काम किया:

# create ~ 100k files
seq 1 99999 | sed "s/\(.*\)/a_somewhat_long_filename_as_a_prefix_to_exercise_zip_parameter_processing_\1.txt/" | xargs touch
# see if zip can handle such a list of names
zip -q /tmp/bar.zip ./*
    bash: /usr/bin/zip: Argument list too long
# use xargs to batch sets of filenames to zip
find . -type f | xargs zip -q /tmp/foo.zip
l /tmp/foo.zip
    28692 -rw-r--r-- 1 jmullee jmullee 29377592 2017-12-16 20:12 /tmp/foo.zip
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.