2010-02-04 44 views
3

我有一系列的NSFetchedResultsControllers爲一些表格視圖提供動力,並且它們在設備上的表現糟糕透頂,大約在幾秒鐘內。由於它全部在主線程上運行,它在啓動時阻止了我的應用程序,這並不是很好。使用SQLite後端修復預測的NSFetchedResultsController/NSFetchRequest性能?

我調查,原來,謂語的問題是:

NSPredicate *somePredicate = [NSPredicate predicateWithFormat:@"ANY somethings == %@", something]; 
[fetchRequest setPredicate:somePredicate]; 

即抓取實體,稱之爲「東西」,與實體「東西」一多對一對多的關係。這個謂詞是一個過濾器,它將結果限制爲只與某個特定「某事」有關係的事物。

當我刪除測試謂詞時,從4秒到100ms或更短的時間(對於某些極端情況),取出時間(初始performFetch:call)是可接受的。儘管如此,我卻對此感到困擾,因爲它否定了我希望通過Core Data和NSFRC獲得的很多好處,否則這些好處似乎是一個強大的工具。

所以,我的問題是,我該如何優化這個性能?我使用謂詞錯誤?我應該以某種方式修改模型/模式嗎?還有其他什麼方法可以解決這個問題?這種性能是否會降低? (有數百< 1KB對象的順序。)

,詳情編輯:

下面的代碼:

[fetchRequest setFetchLimit:200]; 
NSLog(@"before fetch"); 
BOOL success = [frc performFetch:&error]; 
if (!success) { 
    NSLog(@"Fetch request error: %@", error); 
} 
NSLog(@"after fetch"); 

更新日誌(以前,我有一些應用的低效率降低這些是更新的日誌,應該儘可能接近最佳狀態,因爲您可以在當前環境下獲得):

2010-02-05 12:45:22.138 Special Ppl[429:207] before fetch 
2010-02-05 12:45:22.144 Special Ppl[429:207] CoreData: sql: SELECT DISTINCT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 LEFT OUTER JOIN Z_1THINGS t1 ON t0.Z_PK = t1.Z_2THINGS WHERE t1.Z_1SOMETHINGS = ? ORDER BY t0.ZID DESC LIMIT 200 
2010-02-05 12:45:22.663 Special Ppl[429:207] CoreData: annotation: sql connection fetch time: 0.5094s 
2010-02-05 12:45:22.668 Special Ppl[429:207] CoreData: annotation: total fetch execution time: 0.5240s for 198 rows. 
2010-02-05 12:45:22.706 Special Ppl[429:207] after fetch 

如果我做同樣的獲取,而不謂詞(通過註釋掉的問題開始的兩行):在次

2010-02-05 12:44:10.398 Special Ppl[414:207] before fetch 
2010-02-05 12:44:10.405 Special Ppl[414:207] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 ORDER BY t0.ZID DESC LIMIT 200 
2010-02-05 12:44:10.426 Special Ppl[414:207] CoreData: annotation: sql connection fetch time: 0.0125s 
2010-02-05 12:44:10.431 Special Ppl[414:207] CoreData: annotation: total fetch execution time: 0.0262s for 200 rows. 
2010-02-05 12:44:10.457 Special Ppl[414:207] after fetch 

20倍的差距。 500ms並不是很好,而且似乎沒有辦法在後臺線程中執行它,或者以其他方式優化我能想到的。 (除了進入一個二進制商店,這是一個非問題,所以我可能會這樣做。二進制商店的性能持續~100毫秒的上述200對象謂詞查詢。)

(我在此之前嵌套另一個問題,我現在moved away)。

+0

我想這與多對多關係的ANY檢查有關,但是,如果這是問題,我會在這種情況下與Core Data分享您的失望。 – gerry3 2010-02-04 05:46:28

+0

一個隨機想法:不要使用謂詞獲取;相反,獲取所有內容並修改運行時行爲。 (例如,在tableviewcontroller中,如果對象與謂詞不匹配,則顯示其高度爲0的行)。但是,這將是愚蠢的。 – Jaanus 2010-02-05 18:29:26

回答

0

對我來說,實際的解決方案就是切換到具有更好性能的Core Data二進制存儲。我沒有調查我是否可以使用當前的應用程序情況改進Core Data SQLite的性能。

+1

將二進制故事100%加載到內存中。如果你有足夠大的數據集有一個謂詞問題,那麼你只是把它換成了一個內存問題。更好的謂詞是解決這個問題的正確方法。 – 2010-03-31 16:43:44

+0

我有足夠小的數據集和實體,可以使用擴展內存。按照你的建議去擺脫NSFRC並使用準系統陣列工作會更準確。我可能會這樣做,尤其是考慮到我不使用NSFRC委託或其他高級功能(Jeff LaMarche描述了NSFRC修改部分的問題)。 – Jaanus 2010-03-31 17:46:41

4

對於我們中的很多人來說,這是一個持續的問題,試圖在iPhone上使用Core Data來處理更大的數據庫或更復雜的模式。我的個人資料有一些與此相關的幾個不同的SO問題 - 在全文搜索的背景下。

並非所有的應用程序都只是通過將謂詞應用於多對多關係而變得很慢,所以還有更多。見Apple's performance document。 Set -com.apple.CoreData.SQLDebug 1.

檢查是否有索引(如果適用)。確保沒有sql函數(例如格式/類型轉換)被調用,從而使sqlite無法有效地加入或使用索引。

如果您有很多行並且實體中有很多屬性,則可能會出現內存問題。考慮將一個單獨的實體拆分爲一個較小的實體,並使用一些用於搜索的屬性,並在需要時將剩餘的實體拉入其餘實體中。

如果您的謂詞比多對多關係部分更復雜,那麼您可以嘗試兩步搜索。例如。 SQL可能無效地加入,然後過濾而不是篩選,然後加入。但是這樣做會破壞NSFetchedResultsController。不過,這可能會讓問題更加清楚。

我不會像把ObjectIDs包裝成一個屬性來做你自己的一對多外鍵引用。聽起來像一個可怕的黑客肯定勸阻你使用核心數據認真......但核心數據的優勢是衆多。

嘗試刪除或添加反向關係。我發現在一個案例中,我的查詢運行速度快得多,沒有反向關係。缺點是刪除反向關係臃腫我的數據庫。

讓我們知道你在找什麼。

+0

iPhone不支持sqldebug afaik,使調試有點困難。感謝您的其他提示,將盡力。 – Jaanus 2010-02-04 13:43:30

+0

對二元商店進行了初步測試,其中沒有任何這些問題存在。我實際上並不需要SQLite,我需要最大限度地發揮合理的小數據性能,所以二進制存儲可能對我更好。 – Jaanus 2010-02-04 18:09:52

+1

是的,iPhone確實支持SQLDebug。選擇可執行。選擇信息。添加參數-com.apple.CoreData.SQLDebug 1. PS。如果你的數據很小,那麼我更驚訝你看到SQLite性能下降。我懷疑你的代碼有問題。 – 2010-02-05 02:49:02

0

二進制故事會將整個數據集加載到內存中,這會在某些設備上導致內存問題。相反,你應該重新編寫你的謂詞。

既然你們的關係是雙面的(權利?),你可以從另一面來,你可能根本不需要NSFetchedResultsController這種情況。假設你有:

MyWidgetEntity < --- >> SomethingEntity

既然你已經有了SomethingEntity的實例的引用您剛纔問它通過它的插件:

id widget = [mySomethingInstance valueForKey:@"widget"]; 

的情況在這裏你有:

MyWidgetEntity < < - >> SomethingEntity

你可以通過訪問所有相關部件的:

NSSet *widgets = [mySomethingInstance valueForKey:@"widgets"]; 

沒有NSFetchedResultsController需要的,因爲你可以把這個集合到一個數組和排序。

+0

這裏唯一值得關注的是我不得不重新實現像sectionNameKeyPath這樣的NSFRC的一些便利片段,我一直都懶得做。 :) – Jaanus 2010-03-31 17:44:21