Предикат "IN" очень медленный на устройстве (разница в 83 раза) - PullRequest
2 голосов
/ 19 июня 2011

У меня есть предикат

предикат = [NSPredicate предикатWithFormat: @ "character.id IN% @", индексы];

генерирует следующий SQL:

CoreData: sql: SELECT t0.Z_ENT, t0.Z_PK, t0.Z_OPT, t0.ZCHARACTERID, t0.ZMEANING, t0.ZREADING, t0.ZRADICAL, t0.ZSTROKECOUNT, t0.ZCHARACTER, t0ZZ ZGRADE, t0.ZJLPTLEVEL, t0.ZKUNREADING, t0.ZHWUNMEANING, t0.ZROMAN, t0.ZHWUN, t0.ZHWUNMORE, t0.ZPHONETICID ИЗ ZCHARACTERINFO t0. ЛЕЗКИЙ ЦАРТ, ТАР. IN (?,?,?,?,?,?,?) И t0.Z_ENT =?) ORDER BY t0.ZSTROKECOUNT, t1.ZUNICODE

В симуляторе я получил следующий результат:

CoreData: аннотация: время выборки sql-соединения: 0,0478 с CoreData: аннотация: общее время выполнения выборки: 0,0483 с для 7 строк.

VS на устройстве (iPhone 3G)

CoreData: аннотация: время выборки sql-соединения: 3,9627 с CoreData: аннотация: общее время выполнения выборки: 3,9789 с для 7 строк.

План запроса объяснения SQLite показывает, что я использую индекс (индекс ZID определен в модели):

selectid    order       from        detail                                                                                      
----------  ----------  ----------  ---------------------------------------------------------------------------------------------
0           0           0           SEARCH TABLE ZCHARACTERINFO AS t0 USING INDEX ZCHARACTERINFO_Z_ENT_INDEX (Z_ENT=?) (~10 rows)
0           1           1           SEARCH TABLE ZCHARACTER AS t1 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)                 
0           0           0           EXECUTE LIST SUBQUERY 1                                                                     
0           0           0           USE TEMP B-TREE FOR ORDER BY                                                                
CPU Time: user 0.000395 sys 0.000184

В базе данных у меня есть 20 900 строк в таблице символов и 62 000 строк в таблице символов.

Мне интересно, почему это так медленно на устройстве. Я что-то пропустил? Есть ли способ улучшить? Спасибо.

ОБНОВЛЕНИЕ: Я подозревал, что проблема в соединении. Поэтому я попытался переместить t1.ZID в таблицу t0, чтобы избавиться от таблицы соединений. Новый запрос стал:

ВЫБРАТЬ t0.Z_ENT, t0.Z_PK ОТ ZCHARACTERINFO t0 ГДЕ (t0.ZCHARACTERID В (?,?,?,?,?,?,?) И t0.Z_ENT =?) ЗАКАЗАТЬ ПО t0.ZSTROKECOUNT

Новый запрос использовался около 1,8 с. Это было улучшено, но все еще кажется медленным. Это должно быть так медленно?

Ответы [ 2 ]

1 голос
/ 19 июня 2011

Медлительность вашего первого запроса была более чем вероятна из-за LEFT OUTER JOIN.

Исходя из размера вашей базы данных, о котором вы сообщили, я бы сказал, что 1,8 секунды - это действительно быстро, особенно на iPhone 3G.

Если это все еще не достаточно быстро, я бы порекомендовал использовать базу данных более низкого уровня, которая позволит вам напрямую манипулировать схемой вашей базы данных и использовать другие инструменты для ускорения ваших запросов.

0 голосов
/ 20 июня 2011

Спасибо всем за помощь. Решил проблему.

  1. Соединение довольно медленное. Исключено соединение и время до 1,8 ~ 2 с. (см. обновление выше)
  2. Запрос не использовал индекс или использовал только индекс для Z_ENT. Для ZCHARACTERID это все еще делает полное сканирование таблицы. Поэтому я добавил «CREATE INDEX CID_Z_ENT_INDEX ON ZCHARACTERINFO (ZCHARACTERID, Z_ENT). Время запроса сократилось до 0,05 с.

ПРИМЕЧАНИЕ. Каким-то образом после добавления нового индекса план запроса объяснения все еще показывает, что он использует индекс Z_ENT. Необходимо удалить индекс Z_ENT, чтобы можно было использовать CID_Z_ENT_INDEX. Не знаю почему.

...