如何提高iPhone上的核心数据提取性能? [英] How can I improve core data fetch performance on the iPhone?

查看:119
本文介绍了如何提高iPhone上的核心数据提取性能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

核心数据在iPhone上的表现是绝对凄惨的。

Core data's performance on the iPhone is absolutely miserable. Is indexing completely broken or is it just a poor implementation?

我的核心数据存储(SQLite后备存储)中有大约21500个单一类型的对象。对象在作为NSString的UUID上索引(例如,看起来像这样:6b09e200-07b6-11df-a245-002500a30d78)。

I have about 21500 objects of a single type in my core data store (SQLite backing store). The objects are indexed on a UUID which is an NSString (for example, one looks like this: "6b09e200-07b6-11df-a245-002500a30d78").

fetch其中对象存在使用executeFetchRequest在NSManagedObjectContext大约0.75秒!这是最简单的uuid == $ UUID的谓词,其中$ UUID是一个类似上面例子的字符串。

A single fetch where the object exists using executeFetchRequest in NSManagedObjectContext takes about 0.75 seconds! This is with the simplest possible predicate of "uuid == $UUID" where $UUID is a string like the example above.

这真的很奇怪。如果我想在我的商店中获取每个对象,一个接一个,这将需要近4.5个小时!

This is really surprising. If I wanted to fetch every object in my store, one by one, it would take nearly 4.5 hours!

有没有反正改善这种性能,或者我应该放弃核心数据一起吗?

Is there anyway to improve this performance or should I just abandon core data all together?

推荐答案

几点。如果获取21,500行需要5秒钟,则看起来您正在旧设备上运行。像一个3G或原始的iPhone。在这些上的内存和I / O性能只是平缓。您将需要非常小心地处理您的数据,以避免将其读入内存和做不必要的I / O。你可能会发现-setFetchBatchSize特别有用。如果你在3GS上运行,10-20万行是可管理的,但需要小心。如果你在ipad或iphone4上,这不应该是一个问题。

Several points. If it takes 5 seconds to fetch 21,500 rows, it sounds like you're running on an older device. Like a 3G or original iPhone. The memory and I/O performance on those is just plain slow. You'll need to handle your data with extreme care to avoid reading it all into memory and doing unnecessary I/O. You may find -setFetchBatchSize particularly useful. If you're running on a 3GS, 10-20 thousand rows is manageable but will require care. If you're on an ipad or iphone4, this shouldn't be much of an issue.

你不需要创建自己的UUID,除了界面外部系统,像服务器。每个受管对象都有一个objectID,它是其主键的OOP表示。只需传递objectID,并执行类似@self =%@或@self IN%@的查询,通过其ID或数组来搜索对象。您还可以使用-existingObjectWithID:error:只通过其objectID查找1个对象,这将比具有通用谓词的通用获取请求更快。

You don't need to create your own UUID, except to interface with an external system, like a server. Each Managed Object has an objectID which is an OOP representation of its primary key. Just pass the objectID around, and do queries like @"self = %@" or @"self IN %@" to search for an object by its ID or an array of ids. You can also use -existingObjectWithID:error: to look up just 1 object by its objectID which will be faster than a generic fetch request with a generic predicate.

验证索引是否正在使用,因为您期望的是在模拟器中使用可执行参数运行应用程序

The best way to verify the index is being used as you expect is to run the app in the simulator with the executable argument

-com.apple.CoreData.SQLDebug 1

-com.apple.CoreData.SQLDebug 1

将记录到控制台生成的SQL。你应该看到一些以t0.uuid ==?结尾的东西。

that will log to console the SQL being generated. You should see some stuff ending in something like t0.uuid == ?

你可以使用SQL select语句,并通过SQLite的解释查询工具运行它。对模拟器中的db文件运行/ usr / bin / sqlite3。

You can take that SQL select statement, and run it through SQLite's explain query facility. Run /usr/bin/sqlite3 against the db file in the simulator. Do


.explain ON
解释查询计划copythatsqllinehere

.explain ON explain query plan copythatsqllinehere

它应该打印出一些像
0 | 0 |表ZFOO AS t0 WITH INDEX something

it should print out something like 0|0|TABLE ZFOO AS t0 WITH INDEX something

那么您在创建Core Data存储库的方式(您确定模型已标记为索引uuid?)或您的获取请求中还有其他问题时遇到了一些问题。

if it's missing "with index" then you have some issue with either the way you created the Core Data store (are you sure the model is marked to index uuid ?) or there's something else with your fetch request.

这真的很奇怪。如果我想在我的商店中逐一获取每个对象,那么它将花费近4.5个小时!

This is really surprising. If I wanted to fetch every object in my store, one by one, it >would take nearly 4.5 hours!

做到这一点,作为最痛苦的方式之一。或者你可以使用-setFetchBatchSize:并且很快对对象的批次进行迭代。

I suppose you could do it that way, as one of the most painful ways possible. Or you could use -setFetchBatchSize: and iterate over batches of the objects very quickly.

另外,请记住,每个fetch都是I / O与数据库保持与任何其他线程保存的同步。获取不是一些神奇的字典查找。执行最小单位I / O所需的时间有一个下限。您将要分摊各个I / O请求的数量以获得最佳性能。

Also, keep in mind that each fetch does I/O with the database to remain in sync with what any other threads have saved. Fetching is not some magical dictionary look up. There's a lower bound on the time it takes to execute the smallest unit of I/O. You're going to want to amortize the number of individual I/O requests to get the best performance. You'll have to balance that against reading too much into memory at once.

如果您仍然遇到问题,请使用bugreport.apple.com提交错误

If you continue to have trouble, please file a bug with bugreport.apple.com



这篇关于如何提高iPhone上的核心数据提取性能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆