Sqlite + 80K строк + LIKE = отставание клавиатуры - PullRequest
2 голосов
/ 04 мая 2009

У меня была проблема, которую я откладывал, но сейчас самое время.

У меня есть базовая словарная программа. У него есть UISearchBar и UITableView. Он работает так, как должен, за исключением того, что при запуске на устройстве он вызывает отставание клавиатуры. (Симулятор в порядке, конечно) У меня есть два типа поиска. По мере ввода и возврата. Я считаю, что для возврата результатов обеим операциям требуется примерно одинаковое время, но при вводе с клавиатуры клавиатура задерживается.

У меня есть UISearchBar textDidChange, который принимает searchText и отправляет его в метод поиска, который выполняет все подъемы sqlite, помещает результаты в массив. Перезагружает таблицу.

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
    if((searchType == SEARCH_AS_YOU_TYPE) && ([searchText length] >= 2)){
        NSString *myKeyword = [NSString stringWithFormat:@"%@", searchText];
        [self search:myKeyword];
        [myTableView reloadData];
    }
}

Я ограничиваю результаты до 50. И в моем SQL-запросе используются LIKE и OR, но пока нет.

SELECT WORD_ID, DEFIN, PINYIN, SIMP, TRAD from WORDS where DEFIN LIKE "%to dog %" OR DEFIN LIKE "%dog" OR DEFIN LIKE "%dog%"  ORDER BY DEFIN LIMIT 50

Я также пытался переместить [myTableView reloadData] в метод поиска, в надежде, что клавиатура, по крайней мере, не запаздывает. Нет радости И, к сожалению, я знаю, что sqlite в основном проверяет каждую строку, когда использует оператор like. Но 3-4 секунды для 80-и секунд кажутся немного медленными.

Любые мысли, идеи, комментарии или предложения будут с благодарностью!

Ответы [ 5 ]

8 голосов
/ 04 мая 2009

Мне кажется, что вы ищете и готовите клавиатуру в одной теме. Таким образом, вы будете искать столько раз, сколько у вас символов, и скорость набора ограничена скоростью поиска.

Правильное решение состоит в том, чтобы разделить это на две темы: одну для чтения и отображения клавиатуры, вторую для поиска и отображения результатов поиска. Таким образом, если вы печатаете быстрее, чем вы можете искать, задержка будет только при поиске, но не при наборе. Например, адресная строка Firefox работает таким образом.

Ваш код будет более сложным из-за двух потоков и связи / координации между ними, но я думаю, что это единственное хорошее решение.

3 голосов
/ 04 мая 2009

Вот как я предполагаю, что SQLite выполняет этот запрос:

  1. Найдите все строки, которые соответствуют одному из ваших операторов LIKE.

  2. Сортировать их по DEFIN.

  3. Усечение результатов после первых 50 строк.

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

1 голос
/ 06 мая 2009

Поскольку вы используете LIKE, sqlite не будет использовать индекс и будет последовательно сканировать с начала до достижения предела в 50 записей в наборе результатов. В зависимости от порядка ваших данных они могут попасть в первые 50 результатов в начале или в конце худшего случая.

Как насчет того, чтобы создать новый столбец, в котором будет храниться первая буква каждого из базовых слов, например d для собаки и т. Д., И индексировать этот столбец.

Измените свой запрос, чтобы выбрать * из слов, где fisrtletter =: порядок первого письма с определенным лимитом 50

Это значительно сократит ваше пространство поиска

Использование оператора like для полного соответствия

вы также можете предварительно упорядочить данные, чтобы упорядочить их по необходимости не было, я подозреваю, что упорядочение по данным приведет к сканированию полной таблицы, а не к ее завершению при попадании первых 50 записей

0 голосов
/ 04 мая 2010

Я обычно использую

[self performSelectorInBackground:@selector(threadedFetch) withObject:nil];

в сочетании с NSFetchedResultsController Core Data для запуска выборки при вводе пользовательского поиска. Но будьте осторожны при наступлении. Используйте отдельный NSManagedObjectContext для каждого потока или используйте отдельный контекст, который вы блокируете с помощью -[NSManagedObjectContext lock].

0 голосов
/ 04 мая 2009

Попробуйте сделать поисковый запрос в другой ветке. Поскольку операции пользовательского интерфейса выполняются только в основном потоке, любые длительные операции, выполняемые в основном потоке, будут задерживать операции пользовательского интерфейса.

...