2011-09-01 17 views
7

मेरे आईफोन एप्लिकेशन में Words गुण word, length और language गुणों के साथ एक इकाई है। दोनों अनुक्रमित हैं: Entity and attributesसरल कोर डेटा फ़ेच बहुत धीमा है

मैंने सीडीटामोडेल और डेटाबेस को एक अलग आयातक एप्लिकेशन में कॉपी किया जहां इसे विभिन्न भाषाओं में लगभग 400k शब्दों के साथ prefilled मिला। मैंने SQLite फ़ाइल को देखकर आयात की पुष्टि की और फिर आईफ़ोन प्रोजेक्ट में प्रीफिल्ड डेटाबेस की प्रतिलिपि बनाई।

सबसे पहले मैंने सोचा कि (सरल) भविष्यवाणी समस्या है।

// Get word 
NSLog(@"Start"); 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Words" inManagedObjectContext:appDelegate.managedObjectContext]; 
[fetchRequest setEntity:entity]; 

NSError *error = nil; 
NSArray *fetchedObjects = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error]; 
if (fetchedObjects == nil) { 
    //... error handling code 
} 

[fetchRequest release]; 
NSLog(@"End"); 
return fetchedObjects; 

डेटाबेस में प्रविष्टियों की संख्या है:

2011-09-01 09:26:38.945 MyApp[3474:3c07] Start 
2011-09-01 09:26:58.120 MyApp[3474:3c07] End 

यहाँ क्या मेरी कोड लगता है कि है: लेकिन लाने का अनुरोध से विधेय हटाने के बाद भी, यह निष्पादन के लिए एक बहुत लंबा समय लगता है कोर डेटा के लिए एक समस्या?


संपादित: रूप gcbrueckmann और jrturton ने कहा, यह fetchBatchSize स्थापित करने के लिए एक अच्छा सवाल है। लेकिन लाने समय अभी भी नाकाफी है:

  • 2 एक विधेय सेट के साथ सेकंड:

    NSPredicate * विधेय = [NSPredicate predicateWithFormat: @ "लंबाई ==% d और भाषा BEGINSWITH% @", wordLength, एलएनजी ]; [fetchRequest सेट प्रमाणीकरण: predicate];

    :

  • 7 बैच का आकार सेट के साथ सेकंड [fetchRequest setFetchBatchSize: 1];

  • 1 एक दोनों विधेय और बैच आकार के साथ दूसरे सेट

वहाँ अभी भी एक और अड़चन है?

+0

अपने विधेय में लंबाई से संभवतः अधिक प्रतिबंधात्मक भाषा, कभी कभी विधेय चेकों के आदेश के रूप में अच्छी तरह से चीज़ों को गति कर सकते हैं। उदाहरण के लिए यदि इस मामले में 60% शब्द आपके लंबाई मानदंडों को पूरा करते हैं लेकिन केवल 40% भाषा मानदंडों को पूरा करते हैं तो पहले भाषा की जांच करना बेहतर होगा। दूसरी बात यह हो सकती है कि आपको इसकी तेज़ी से आवश्यकता हो, तो इसे प्री-लोड किया जाना चाहिए और फिर स्मृति में एक सरणी फ़िल्टर करना सुनिश्चित करें कि आपका आईफोन ऐप इसे संभाल सकता है या नहीं। –

+0

इस मामले में पहली क्वेरी पूर्णांक की तुलना कर रही है (इंडेक्सिंग इसे बहुत तेज़ कर देगा) और दूसरा एक स्ट्रिंग तुलना है (यहां तक ​​कि एक अनुक्रमित स्ट्रिंग भी तेज़ी से नहीं जा रही है) - अगर क्वेरी की पुनरीक्षण में मदद मिली तो मुझे आश्चर्य होगा। हालांकि, इसे आज़माएं - मुझे यह देखने में दिलचस्पी होगी कि इससे मदद मिली है या नहीं! – deanWombourne

+0

ओह, मैं इसका उल्लेख करना भूल गया: मैंने पहले ही भविष्यवाणी के आदेश को स्वैप करने की कोशिश की है, यह fetch को तेज नहीं करता है। – Norbert

उत्तर

11

चूंकि आप एक बार में 400,000 वस्तुओं को लाने के परिणामस्वरूप परिणाम सेट को सीमित नहीं कर रहे हैं, निश्चित रूप से कोर डेटा पर बोझ होगा।

बदलने लाने का अनुरोध के fetchBatchSize वस्तुओं लाने एक समय में स्मृति में रखना होगा की संख्या को सीमित: आप कई तरीकों से प्रदर्शन में सुधार कर सकते हैं। यह सुविधा आपके एप्लिकेशन के लिए पूरी तरह से पारदर्शी है, इसलिए यह निश्चित रूप से प्रयास करने योग्य है।

यदि आपको पूरी तरह से वस्तुओं की आवश्यकता नहीं है, तो आप fetch अनुरोध के resultType को अधिक उपयुक्त मान में बदलने पर विचार कर सकते हैं। विशेष रूप से यदि आप किसी ऑब्जेक्ट के कुछ मानों में रुचि रखते हैं, तो NSDictionaryResultType का उपयोग करना एक अच्छा विचार है।

आखिरकार fetchLimit और fetchOffset गुण आपको परिणाम सीमा को सीमित करने की अनुमति देते हैं, यदि आप बैच प्रोसेसिंग को प्रबंधित करना चाहते हैं। यह एक अच्छा विचार है कि प्रत्येक परिणाम ऑब्जेक्ट्स का आपका प्रबंधन बहुत सारी मेमोरी का उपयोग करता है क्योंकि आप प्रत्येक बैच को NSAutoreleasePool में लपेट सकते हैं (केवल प्रत्येक एकल ऑब्जेक्ट ऑब्जेक्ट के लिए ऑटोरेलीज पूल बनाने के लिए लुभाने की कोशिश न करें)।

मुझे लगता है कि 1 सेकंड। हो सकता है कि यह आपके मामले में जितना तेज़ हो सके - भले ही आप सादे स्क्लाइट डेटाबेस का सहारा लें। एकमात्र और अनुकूलन मैं सोच सकता हूं कि प्रति भाषा एक टेबल का उपयोग करना है (सभी भाषाओं से शब्दों को एक ही तालिका में डालने के बजाय)। यह, ज़ाहिर है, केवल स्क्लाइट के साथ काम करेगा जब तक आप सभी भाषाओं के लिए अलग-अलग इकाइयों को परिभाषित नहीं करते हैं, i। ई। अपनी Words इकाई को ले जाएं और इसे सार बनाएं। फिर EnglishWord आदि जैसे उपखंड जोड़ें। विभिन्न इकाइयों के ऑब्जेक्ट अलग-अलग तालिकाओं में संग्रहित होते हैं। इसलिए, fetchBatchSize और predicate पैरामीटर के साथ संयुक्त यह सभी भाषाओं के लिए अलग-अलग तालिकाओं के साथ स्क्लाइट दृष्टिकोण के समान प्रदर्शन करना चाहिए।

+0

'fetchBatchSize' निश्चित रूप से एक अच्छा बिंदु है। लेकिन दुर्भाग्यवश यह अभी भी एक शब्द को पकड़ने में 2 सेकंड लगते हैं। – Norbert

+0

अपने मामले में एक नंगे-हड्डियों Sqlite डेटाबेस एक विकल्प का उपयोग कर रहा है? ऐसा लगता है कि मौजूदा ऑब्जेक्ट्स संशोधित नहीं हैं, इसलिए कोर डेटा में शायद (एम) सादे स्क्लाइट पर कोई लाभ नहीं होगा। 400,000 वास्तव में आईफोन पर एक बड़ा डेटासेट है। क्या प्रति भाषा एक टेबल रखने का विकल्प होगा? – gcbrueckmann

+0

हां, मैंने पहले से ही सादे SQLite पर स्विच करने के बारे में सोचा था, लेकिन मैंने सोचा कि अभी भी एक बाधा हो सकती है जिसे मैं नहीं देख सकता। – Norbert

1

इससे आपके पूरे 400k डेटाबेस को मेमोरी में लाया जाएगा जो बहुत कुछ लगता है। आप NSFetchRequest के

setFetchBatchSize 

विधि है जो आपकी लाने का अनुरोध में सब कुछ के लिए पूर्ण वस्तुओं लौटने ढांचे बंद हो जाता है, इस धारणा है कि आप हर लौटे वस्तु की जरूरत नहीं है पहले उदाहरण में दुकान से लाना पर जांच कर सकता है।

2

आप BEGINSWITH कर रहे हैं - यह बहुत तेज़ ऑपरेशन नहीं है! हालांकि, भाषाओं की एक सीमित संख्या है इसलिए एक ईम शायद मदद करेगा।

एक भाषा_आईडी फ़ील्ड है जो एक अनुक्रमित पूर्णांक है और अपने भविष्य में इसका उपयोग करें। तुम अब भी रूप में अच्छी तरह भाषा नाम स्टोर कर सकते हैं और प्राप्त किए गए वस्तु के हिस्से के रूप में यह लौटने के लिए, बस उस पर खोज नहीं है :)


पुनश्च आप -com.apple जोड़कर एसक्यूएल डीबग किया जाना चालू कर सकते हैं। एक तर्क लांच पर पारित (अपनी योजना में इस कॉन्फ़िगर) के रूप में CoreData.SQLDebug 1 '- यह आप देख एसक्यूएल पर्दे के पीछे क्या कर रहा है मदद कर सकता है।

(अधिक जानकारी के लिए this question देखें)

+0

'भाषा BEGINSWITH% @' ले लिया 600 मि.से (औसत); 'भाषा ==% @' 350ms (औसत) ले लिया! – Norbert

+1

मुझे विश्वास है कि इन पंक्तियों के साथ मैंने यह भी देखा है कि यह भाषा की तुलना की तरह चीजें करने के लिए कहा जाता है> =% @ BEGINSWITH का उपयोग करने से तेज़ होने के नाते। मैं कहना चाहता हूं कि यह 2010 डब्ल्यूडब्ल्यूडीसी कोर डेटा वीडियो में था। –

+0

यदि यह अभी भी स्ट्रिंग समानता है तो आप पूर्णांक की तुलना करने के लिए कनवर्ट करते समय भी अधिक गति प्राप्त करने जा रहे हैं;) एसक्यूएल में स्ट्रिंग इंडेक्सिंग केवल स्ट्रिंग में वर्णों की एक निश्चित संख्या को मानती है जबकि एक पूर्णांक अनुक्रमणित करना आदर्श है! - http://dev.mysql.com/doc/refman/5.0/en/create-index.html – deanWombourne

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