2012-10-03 18 views
6

मैं एक स्थानीय SQLite डेटाबेसSQLite - SQLite डेटाबेस से डेटा पढ़ने का सबसे तेज़ तरीका?

टेबल विवरण

-- Describe PREFIX_LIST 
CREATE TABLE PREFIX_LIST(ITEM VARCHAR(25) PRIMARY KEY) 

-- Describe SUFFIX_LIST 
CREATE TABLE SUFFIX_LIST(ITEM VARCHAR(25) PRIMARY KEY) 

-- Describe VALID_LIST 
CREATE TABLE VALID_LIST (
    "PART1" TEXT, 
    "PART2" TEXT, 
    PRIMARY KEY(PART1, PART2) 
) 

है अब इस सूची वास्तव में बहुत बड़ा है, और मैं इसे से डेटा को बचाने की जरूरत की जरूरत है।

यहां मेरा कार्यान्वयन है।

SQLiteConnection con = null; 
SQLiteCommand cmd = null; 
Connect(DbPath, ref con, ref cmd); 

cmd.CommandText = 
    "SELECT PART1 || '@' || PART2 FROM VALID_LIST 
WHERE NOT EXISTS 
    (SELECT * FROM PREFIX_LIST WHERE VALID_LIST.PART1 LIKE '%' || ITEM || '%') 
    AND NOT EXISTS 
    (SELECT * FROM SUFFIX_LIST WHERE VALID_LIST.PART2 LIKE '%' || ITEM || '%')"; 

var reader = cmd.ExecuteReader(); 

if (reader.HasRows) 
{ 
    string savePath; 

    if (SaveTextFile(out savePath) == DialogResult.OK) 
    { 
     TextWriter writer = new StreamWriter(savePath); 
     while (reader.Read()) 
     { 
      writer.WriteLine(reader.GetString(0)); 
     } 
     writer.Close(); 
     writer.Dispose(); 
    } 

} 

reader.Close(); 
reader.Dispose(); 
cmd.Dispose(); 
con.Close(); 
con.Dispose(); 

MessageBox.Show("List Saved!.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); 

मुझे कुछ बेहतर तरीके की आवश्यकता है जिससे मैं सूची को तेज़ी से सहेज सकूं। VALID_LIST में कुल प्रविष्टियों 2639117

है और यह 15 मिनट के ऊपर SQL क्वेरी के लिए सहेज लिया!

कृपया एसएमएल क्वेरी अनुकूलित किया जा सकता है तो कृपया lmk कृपया!

पहले से LIKE साथ

+2

सहसंबंधित सबक्वायरी + 'LIKE' = विशाल प्रदर्शन हिट – cdhowie

+0

@cdhowie - मुझे पता है, लेकिन अन्य समाधान क्या हैं? मुझे लगता है कि क्वेरी किसी भी तरह अनुकूलित किया जाना चाहिए! –

+0

मुझे नहीं लगता कि आपकी स्कीमा को पूरी तरह से बदलने के बिना इसे अनुकूलित करने का एक आसान तरीका है। – cdhowie

उत्तर

6

प्रश्नों धन्यवाद जब तक वाइल्डकार्ड प्रत्यय से जुड़ा हुआ है सामान्य रूप में बहुत धीमी गति से होने जा रहे हैं। एक अनुमान जैसे LIKE '%foo' को सामान्य स्ट्रिंग इंडेक्सिंग के माध्यम से अनुक्रमित नहीं किया जा सकता है।

हालांकि आप अपने full text search (एफटीएस) सुविधा के साथ एसक्लाइट में भारी LIKE उपयोग को प्रतिस्थापित कर सकते हैं।

FTS3 और FTS4 विस्तार मॉड्यूल उपयोगकर्ताओं के साथ विशेष टेबल बनाने की अनुमति देता निर्मित एक पूर्ण-पाठ सूचकांक (इसके बाद "FTS टेबल")। पूर्ण पाठ इंडेक्स में तालिका कई बड़े दस्तावेज शामिल हैं, उपयोगकर्ता कुशलता से सभी पंक्तियां एक या अधिक शब्दों (इसके बाद "टोकन") होते हैं के लिए डेटाबेस क्वेरी करने के लिए अनुमति देता है।

उनके पास an example है जो आपके उपयोग के मामले में प्रदर्शन के मामले में आशाजनक दिखते हैं।

CREATE VIRTUAL TABLE enrondata1 USING fts3(content TEXT);  /* FTS3 table */ 
CREATE TABLE enrondata2(content TEXT);      /* Ordinary table * 

SELECT count(*) FROM enrondata1 WHERE content MATCH 'linux'; /* 0.03 seconds */ 
SELECT count(*) FROM enrondata2 WHERE content LIKE '%linux%'; /* 22.5 seconds */ 
+0

मुझे लगता है कि आपके पास पीछे की ओर है - उपसर्ग इंडेक्स का उपयोग कर सकते हैं, लेकिन प्रत्यय नहीं कर सकते हैं। – cdhowie

+0

@cdhowie मैं सहमत हूं, मैं इस बात का जिक्र कर रहा था कि वाइल्डकार्ड कहाँ चिपक गया था। मैंने अपना जवाब स्पष्ट किया है। –

+0

मैं देखता हूं कि अब आपका क्या मतलब है। यह एक ताकत अस्पष्ट था, स्पष्टीकरण के लिए धन्यवाद। सभी जानकारी के लिए – cdhowie

2

पूर्ण पाठ खोज का उपयोग करने पर विचार करें।

इसके लिए काम करने के लिए, PREFIX और SUFFIX में मानों को टोकननाइज़ किया जाना चाहिए (उन्हें अलग शब्द होना चाहिए), और जिस आइटम को आप मिलान करने का प्रयास कर रहे हैं वह इन मानों में से एक में एक विशिष्ट टोकन होना चाहिए (भाग नहीं एक शब्द या दो शब्दों के साथ)। उदाहरण के लिए, उपसर्ग और प्रत्यय में तार 'लाल नीले, हरे' या 'कुत्ते, बिल्ली, capybara' और आइटम के लिए मान लाल होना चाहिए, नीला, हरा, कुत्ते, बिल्ली, या Capybara की तरह कुछ होना है।

उन परिस्थितियों आप, पूर्ण पाठ खोज सक्षम पूरी पाठ तालिका के रूप में इन तालिकाओं को पुनः, और मैच के साथ की तरह (और वाइल्डकार्ड) की जगह सकता से मुलाकात कर रहे हैं। इस मामले में, SQLite हर टोकन उपसर्ग या प्रत्यय और खोज के उस हिस्से में पाया पर सूचकांक पर बनाए रखने के लिए बहुत, बहुत तेजी से होगा।

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

+0

thnx! ऐसा लगता है कि मुझे अपने समाधान एटीएम पर चिपकना है, भले ही यह धीमा हो! –

+0

क्या यह सच है कि व्यक्तिगत मिलान के खिलाफ आपका मिलान करने वाला आइटम? यदि ऐसा है, तो शब्दों को एक बार में अपनी पंक्तियों में रखें। आप वह काम बहुत जल्दी कर सकते हैं। –

+0

मेरी खराब अंग्रेजी के लिए खेद है, लेकिन मैं एसक्यूएल के माध्यम से क्या करने की कोशिश कर रहा हूं, सुनिश्चित करें कि मेरी सभी वस्तु valid_list.part1 में prefix_list.item –

0

मुझे यकीन नहीं है कि यह वही है जो आप चाहते हैं लेकिन यह लेखन प्रक्रिया को तेज़ी से बढ़ाने में मदद करेगा। स्ट्रिंग बिल्डर में डेटाबेस से पढ़ने वाले तारों को जमा करने का प्रयास करें और फिर फ़ाइल को लिखें। उदाहरण के लिए आप 100k स्ट्रिंग पढ़ सकते हैं, फिर फ़ाइल में उन 100k को एक बार लिखें।

StringBuilder builder = new StringBuilder(); 
    int count = 0; //to limit the number of rows stored in string builder. 
    while (reader.Read()) 
    { 

     builder.AppendLine(reader.GetString(0)); 
     count++; 

     //store every 100k or so rows at once. 
     //This number depends on how much RAM 
     //you can allocate towards storing the string of rows. 
     //If you have 2GB of free RAM 
     //this number can easily be 1 million but it always depends on the 
     //size of each string stored in database. 
     if(count == 100000) 
     { 
      File.AppendAllText(path, builder.ToString()); //Append all rows to the file 
      builder.Clear(); //clear the string for next 100k rows of data 
      count = 0; //Clear the counter value 
     } 
     count++ 
    } 

अगर यह मदद करता है तो मुझे बताएं।

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