2012-01-30 2 views
1

Я получаю плохую производительность и, возможно, странное поведение с простым запросом SELECT в Sqlite & Android. SqliteDatabase.query() выполняет мой запрос всего за 1 мс, но получение результатов с помощью Cursor.get*() занимает более 150 мс, чтобы вернуть только 8 строк!Как повысить производительность моего запроса SELECT в Sqlite/Android?

Я пытаюсь найти все строки в таблице english где столбец word начинается с «приставкой» (произвольная строка), сортировать результаты по row колонку, и возвращать только первые 8 результатов.

Вот мой код:

String columns[] = {"word", "rank"}; 
Cursor cursor = mDB.query("english", columns, "word LIKE '" + prefix + "%'", null, null, null, "rank,word", "8"); 

// It takes only 1 ms to get here 

String word = ""; 
int rank = 0; 
if (cursor.moveToFirst()){ 
    do { 
     word = cursor.getString(0); 
     rank = cursor.getInt(1); 
    } 
    while(cursor.moveToNext()); 
} 

cursor.close(); 

// It takes over 150 ms to get here! 

Определение таблицы для english является:

CREATE TABLE en (_id INTEGER PRIMARY KEY, word TEXT, rank INTEGER) 

Он содержит около 65 000 записей. Он также также индексы на word и rank, с помощью третьего показателя для обоих (я отчаялась!):

CREATE INDEX "rank" ON "en" ("rank" ASC) 
CREATE INDEX "word" ON "en" ("word" ASC) 
CREATE INDEX "word_rank" ON "en" ("word" ASC, "rank" ASC) 

Спасибо заранее!

ответ

2

Метод запроса фактически не извлекает все данные, курсор извлекает его при его перемещении по строкам. Поэтому имеет смысл, что методы Cursor.move *() медленнее, чем запрос.

Эта концепция «ленивой загрузки» помогает экономить память, поскольку только необходимые данные извлекаются по мере необходимости.

Что касается производительности, вы действительно ничего не делаете неправильно. Вы пытаетесь это сделать на эмуляторе? Возможно, попробуйте его на самом устройстве и проверьте производительность.

+1

Hi Kane. После того, как я опубликовал свой вопрос, я обнаружил, что узким местом является cursor.moveToFirst(), что имеет смысл с тем, что вы сказали. Я запускаю его на самом устройстве, но производительность имеет решающее значение, потому что мое приложение представляет собой IME (мягкая клавиатура), и запрос ищет словарные совпадения, поэтому он должен быть быстрее, чем нажатие клавиши. 150 + ms слишком медленно. :( –

+2

Barry, 150ms работает слишком медленно, если вы выполняете запрос в потоке пользовательского интерфейса. Вам обязательно нужно посмотреть на перенос операций с базой данных на отдельный поток и затем отправить результаты обратно в поток пользовательского интерфейса, чтобы обновить список. Для получения информации об этой технике читайте этот http://developer.android.com/resources/articles/painless-threading.html –

+0

Я думал об этом, но есть проблема синхронизации, если пользователь нажимает пробел перед поиском нить находит свое слово: функция автоматического выбора будет вставлять неправильное слово. Однако я еще раз взгляну на этот подход. Спасибо. –