6

मैं ऐसे एप्लिकेशन पर काम कर रहा हूं जो विंडोज मोबाइल 6 पर चलता है जिसे किसी आइटम तालिका से सभी आइटम पुनर्प्राप्त करने में सक्षम होना चाहिए जिसमें आइटम के विवरण फ़ील्ड में दी गई स्ट्रिंग (अंतिम उपयोगकर्ता द्वारा प्रदान की गई) शामिल है। समस्या यह है कि तालिका में लगभग 170,000 आइटम हैं। चूंकि मुझे विवरण में कहीं भी स्ट्रिंग रखने वाली सभी वस्तुओं को वापस करने की आवश्यकता है, इसलिए मुझे LIKE% string% का उपयोग करने के लिए मजबूर होना पड़ता है, जो इंडेक्स का उपयोग करने का कोई मौका समाप्त करता है। डेटा और तालिका संरचना मूल रूप से प्रोग्रेस डेटाबेस पर आधारित होती है, जिसमें किसी भी शब्द-अनुक्रमित फ़ील्ड पर एक अद्भुत शामिल ऑपरेटर होता है। यह हमारे मोबाइल एप्लिकेशन पर मामला नहीं है, क्योंकि यह SQL सर्वर कॉम्पैक्ट 3.5 का उपयोग करता है।एसक्यूएल लायक ऑपरेटर के प्रदर्शन को बढ़ाने के लिए उपयुक्त प्रतिस्थापन क्या है?

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

8m और 42s को छोड़कर, ठीक और बेवकूफ, जो आइटम को पुनर्प्राप्त करने के लिए लेता है, जब मैं विवरण में "गोल्फ" जैसा कुछ आइटम ढूंढता हूं। जाहिर है यह अंतिम उपयोगकर्ता के लिए एक स्वीकार्य समय सीमा नहीं है।

मेरा पहला प्रयास बजाय आइटम से चयन * आइटम से सभी वस्तुओं को वापस प्राप्त करना था (मुख्य अनुक्रमित फ़ील्ड में से किसी एक पर क्लॉज द्वारा ऑर्डर के साथ)। इस बिंदु पर मैंने इंडेक्सऑफ चेक चलाया क्योंकि मैंने भाग लिया SqlCeDataReader और आइटमफैक्टरी केवल सूची ऑब्जेक्ट में आइटम जोड़ता है यदि उनमें अनुरोधित विवरण टेक्स्ट होता है। इससे गति 1 एम 46 तक बढ़ जाती है। बहुत शर्मीली नहीं है, लेकिन अभी भी धीमी है।

मैंने फिर एक और दृष्टिकोण की कोशिश की जो मैंने दिखाया वादा ... लगभग ... एप्लिकेशन शुरू होने पर, मैंने एक सूची बनाने की कोशिश की जिसमें डेटाबेस के भीतर सभी आइटम ऑब्जेक्ट्स शामिल थे (क्वेरी चलाने के लिए लगभग 2 मिनट लगते हैं और पूरी सूची पॉप्युलेट करते हैं, लेकिन कम से कम यह केवल एक बार होता है ऐप शुरू हो रहा है ... अभी भी ... यूघ)। एक बार सूची शिकायत हो जाने पर ईटी, मैं आसानी से उस सूची पर प्रश्नों को चला सकता हूं जैसे कि निम्नलिखित (मुझे उम्मीद है कि मेरा वाक्यविन्यास सही है ... मैं अभी काम पर नहीं हूं और मेरे पास पीसी पर विजुअल स्टूडियो नहीं है):

List<Item> specificItems = 
    AllItems.FindAll(i => i.Description.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0); 

इस दृष्टिकोण ने इसे 21 तक घटा दिया। बहुत अच्छा (चीजों की भव्य योजना में अभी भी धीमा)। हालांकि, समस्या यह है कि अगर मैं डेटाबेस से सभी आइटम लोड करता हूं तो मेमोरी उपयोग बहुत बढ़िया तरीका है। शुरुआती लोड के दौरान मुझे पिछले 20,000 आइटमों को वास्तव में काटना था (इसलिए 21s समय सीमा शायद 25 की तरह अधिक होगी), क्योंकि आउटऑफमेमरी अपवाद को फेंक दिया गया था। एम्यूलेटर पर मेमोरी मैनेजर के मुताबिक, मेरे पास अभी भी लगभग 20 एमबी फ्री रैम था, लेकिन मैंने सुना है कि एक प्रक्रिया में केवल 32 एमबी या रैम हो सकता है (सुनिश्चित नहीं है कि यह डब्लूएम 6 के लिए सच है, लेकिन ऐसा लगता है इसलिए)।

यह सुनिश्चित करने के लिए कि यह सभी वस्तुओं को रखने के लिए सूची वस्तु का उपयोग नहीं कर रहा था (जो मैं गतिशील आकार बदलने से बचने के लिए अपने कन्स्ट्रक्टर में आवश्यक क्षमता के साथ तत्काल क्षमता के साथ तत्काल था), जिसे मैंने पढ़ा है अतिरिक्त कारण हो सकता है स्मृति उपयोग जब यह अनिवार्यता EnsureCapacity कॉल करता है, मैंने एक आइटम [] सरणी (समय से पहले आकार) का उपयोग करने की कोशिश की। इसमें अभी भी स्मृति समस्या थी और आकार अंतर नगण्य था।

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

कोई विचार? क्या मैं इस बारे में गलत तरीके से जा रहा हूं?

सुनने के लिए धन्यवाद (क्षमा करें यह पोस्ट लंबा है, मैं जोर से सोच रहा हूं)।

ओह मैं (सिर्फ सारांश में) जोड़ना चाहिए कि मैं क्या उपयोग कर रहा हूँ:

  • विंडोज मोबाइल 6
  • Sql सर्वर कॉम्पैक्ट संस्करण 3.5
  • # 3.5 सी

अद्यतन: एक ओर जहां नीचे उल्लिखित ब्लूम फ़िल्टर दृष्टिकोण दिलचस्प लग रहा था, मैं एक आवश्यकता को पूरा नहीं कर सका (जिसे मैंने वास्तव में ऊपर निर्दिष्ट नहीं किया था)। मैं वास्तव में उन शब्दों से मेल नहीं खा सकता जो कि दूसरे शब्दों के अंदर निहित हैं (उदाहरण के लिए "क्लब" "क्लब" नहीं लौटाएगा)। इसके कारण, मुझे एक अलग दृष्टिकोण का उपयोग करने के लिए मजबूर होना पड़ा (केंट फ्रेड्रिक ... इसे इंगित करने के लिए धन्यवाद)। मैंने केंट के उत्तर को सही के रूप में चिह्नित किया है, क्योंकि उनका दृष्टिकोण वह था जो सबसे अधिक आवश्यकताओं को पूरा करता था (मिच, आपके पास जंडर द्वारा सुझाए गए ब्लूम फ़िल्टर के समान समस्या थी)। हालांकि, मैं अपने रास्ते से भी एक अलग दृष्टिकोण (अब के लिए ...) चला गया है।

मैंने जो किया है, वह सभी आइटम ऑब्जेक्ट्स को स्मृति में खींच लिया गया है, केवल आइटम संख्याओं और विवरणों के साथ (जो इसे स्मृति सीमाओं के तहत रखता है, हालांकि यह अभी भी मुझे पसंद से अधिक प्रारंभिक कारण बनाता है ... multithreading और लोड हो रहा है दृश्य चलने के दौरान दृश्यों के पीछे की जानकारी मुझे लगता है कि इसका ख्याल रख सकते हैं)। मैंने अपनी खोजों को पूरा करने के लिए नियमित रूप से लिखा है। दिनचर्या अप्रबंधित सी # कोड में लिखा गया है जो विवरण और आवश्यक मिलान पाठ के माध्यम से चलाने के लिए दो पॉइंटर्स और दो लूप का उपयोग करता है। यदि यह विवरण में कहीं भी एक मिलान पाता है, तो यह आइटम संख्या को सरणी में जोड़ता है। एक बार सभी वस्तुओं की खोज हो जाने के बाद, एक नई क्वेरी डेटाबेस पर वापस जाती है और केवल मिलान करने वाली आइटम संख्याओं को पकड़ती है (जो एक पूर्णांक फ़ील्ड पर सूचकांक के कारण बहुत तेज है)। फिर उन वस्तुओं को सभी जानकारी के साथ सूची में बनाया गया है (न केवल आइटम संख्या और विवरण)। पूरे ऑपरेशन में लगभग 5-10 सेकंड लगते हैं (विवरण के आधार पर), जो अब के लिए काफी अच्छा है।

मैं अब भी इसे और अधिक अनुकूलन में देख सकता हूं (यह जानने में सक्षम हो सकता है कि खोज शब्द कितने अक्षर हैं ... यदि आवश्यक टेक्स्ट की तुलना में आइटम विवरण पर कम वर्ण शेष हैं, तो लूप सीधे जारी रख सकता है अगला आइटम)।

कोई भी सुझाव अभी भी स्वागत है। अभी के लिए मैंने अपने प्रश्न के लिए केंट के उत्तर को "सबसे सही" के रूप में चिह्नित किया है।

मुझे रोज़ाना लिखने में मदद करने के लिए डॉल्च की प्रॉप्स।

उत्तर

4

मैंने Mitch Wheat's उत्तर के लिए मतदान किया, लेकिन कुछ चालें हैं जो मैं प्रभावशीलता के लिए भी परीक्षण करूँगा।

[char], [int] से भरा टेबल रखने के बारे में मेरी बड़ी चिंता यह है कि आप अभी भी अपने आप को इस नई तालिका पर% शब्द% का उपयोग करने के लिए व्यर्थ स्ट्रिंग तुलनाओं की बड़ी मात्रा को निष्पादित कर सकते हैं। (डुप्लिकेट लेकिन मेल नहीं-हमारी-खोज प्रविष्टियां)।

मैं शायद

Words 
----- 
chars | word_id 

WordsToEntry 
------------ 
word_id | entry_id 

साथ experimeting के लिए चुनते हैं और देखना होगा यदि डेटाबेस भूमि के ऊपर यह संभव समस्या का एक योग्य शमन है (मैं नहीं कर सकते परीक्षण, खेद)

+0

आपको तालिका पर '% शब्द%' मैच करने की आवश्यकता नहीं होगी, बस एक 'शब्द' मैच, जो इसका उपयोग करने का कारण है। –

+0

समस्या यह है कि यदि आप केवल सफेद स्थान से विभाजित होते हैं, तो आप सभी सीमित शोर टोकन भी ले लेंगे, और साथ ही,% शब्द% के बिना आप उन शब्दों को नहीं ढूंढ पाएंगे जो रचनाओं का हिस्सा हैं, यानी: "कुत्ता" "कुंट मैच" कुत्तों " –

+0

अच्छा बिंदु। इस मामले में यह महत्वपूर्ण है कि एकवचन शब्द बड़े शब्दों के भीतर मौजूद सभी बहुवचन और शब्दों को वापस कर दें। –

5

कैसे पूर्व प्रसंस्करण (एक बार) आइटम तालिका के बारे में (और प्रत्येक नई प्रविष्टि से जोड़ रहे है संसाधित करने की आवश्यकता होगी) अपने सभी आइटम के ऊपर एक शब्द उभरता है

CREATE TABLE WordItemOccurance 
(
    [Word] varchar(50) not null, 

    ItemId int not null 
     constraint FK_Items references ItemTable(ID) 
) 

दोहराएं होने तालिका बनाने के लिए, अलग-अलग शब्दों में तोड़ें और प्राप्ति तालिका में प्रविष्टियां जोड़ें जैसे वे पाए जाते हैं।

[वर्ड] पर क्लस्टर्ड इंडेक्स बनाना और आइटम आईडी पर आइटम टेबल में शामिल होना चाहिए।

+0

शायद-पूर्व प्रक्रिया के लिए आइटम मेज पर एक ट्रिगर नए जोड़े गए प्रविष्टियों (कॉम्पैक्ट समर्थन करता है, तो यह ...) –

+0

नहीं एक बुरा विचार पैदा करते हैं। यह संभवतः मेरे साथ आने वाला दृष्टिकोण होगा, हालांकि ब्लूम फ़िल्टर विचार भी दिलचस्प दिखता है। –

1

आप एक खिलने फिल्टर का उपयोग कर की कोशिश कर सकते ।

  1. wikipedia
  2. using bloom filters
+0

दिलचस्प पढ़ा। ब्याज के लिए बाहर होने पर भी एक दरार लेना उचित है। धन्यवाद जौदर। –

+0

मैं इस दृष्टिकोण का उपयोग करके दूसरे शब्दों के साथ शब्दों को कैसे ढूंढ सकता हूं, इसलिए मुझे नहीं पता कि यह मेरी विशेष परिस्थितियों के लिए सही नहीं है (उदाहरण के लिए "क्लब" को "क्लब" भी लौटा देना चाहिए। –

+0

ब्लूम फ़िल्टर केवल आपको बताते हैं कि कुछ मौजूद है आप जो मांग रहे हैं वह स्थिर क्षमता है। Http://www.google.com/search?q=stemming सूचीबद्ध स्टैमिंग अल्गोस का एक समूह है। –

संबंधित मुद्दे