Iphone Sqlite3 Запрос слишком медленный - PullRequest
0 голосов
/ 09 июля 2010

Здравствуйте, я действительно застрял с моим приложением. Мне нужно сделать простой SELECT для одной из моих таблиц с приблизительно 250 000 строк (50 МБ), используя SQLITE3. Когда я загружаюсь с помощью Iphone Simulator, запрос занимает около 3 секунд. Когда я тестирую свое приложение на устройстве, запрос занимает 90 секунд. К сожалению, я не могу выпустить свое приложение за 90 секунд ожидания. Здесь я публикую свой код:

-(void) loadResults {

sqlite3 *database;
NSMutableString *street;
zone = [[NSMutableArray alloc] init];

if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
    const char *sqlStatement = [[NSString stringWithFormat:@"select street from streets "] UTF8String];
    sqlite3_stmt *compiledStatement;
    if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
        while(sqlite3_step(compiledStatement) == SQLITE_ROW) {

            street = [NSMutableString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
            [zone addObject:street];
        }
    }   
    sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);}   

Вот как я создал свою таблицу, используя SQLITE3

CREATE TABLE streets (id INTEGER PRIMARY KEY, street TEXT, province TEXT, country TEXT, from TEXT, to TEXT, lat TEXT, lon TEXT);
CREATE INDEX strIndx on streets(street);

Как видите, оператора WHERE нет, это просто "ВЫБРАТЬ улицу из улиц"

Пожалуйста, мне нужна помощь здесь Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 09 июля 2010

Если у вас 250 000 строк и только 3000 разных результатов, каждая улица в базе данных в среднем 83 раза.

Возможно, было бы целесообразно разделить ваши улицы в отдельную нормализованную таблицу, где каждое значение встречается только один раз, а затем ссылаться на эти улицы из вашей таблицы адресов по идентификатору. Затем для вашего TableView вы можете извлечь только значения из таблицы Streets.

Как уже упоминалось ранее, у вас также может быть проблема с парадигмой пользовательского интерфейса. Если у вас есть таблица с 3000 записей в пользовательском интерфейсе, это может быть очень утомительным для пользователя. (Представьте, что вы пытаетесь прокрутить вниз один щелчок к улице Ябара.)

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

2 голосов
/ 09 июля 2010

Что вы пытаетесь сделать?Поскольку вы признаете, что у вас нет оператора WHERE, я предполагаю, что вы не делаете ничего, кроме фильтрации строк на стороне Obj-C.Поэтому единственное, что я могу подумать о том, что вы пытаетесь сделать (пожалуйста, прокомментируйте, если я ошибаюсь), это загрузить все строки для отображения.У Apple есть очень простая стандартная рекомендация для этого - ленивая загрузка таблицы.По сути, добавьте ограничение, скажем, 15 строк к исходному запросу, и получите способ получить больше (обычно это будет нижний колонтитул таблицы с синим текстом с надписью «Загрузить больше ...»).В качестве альтернативы это можно реализовать, просто не загружая ячейки ниже предела, пока не будет запрошено (что произойдет, когда пользователь прокрутит их).

0 голосов
/ 09 июля 2010

Спасибо за ваш ответ, Джаред, мне нужно показать все улицы в UITableView и позволить пользователю отфильтровать поиск в UISearchBar или просто позволить ему выбрать его из списка. Я изменил свой запрос на

SELECT DISTINCT(street) from streets

Это вернуло результат 3000 строк, но это занимает столько же времени, что и без DISTINCT, то есть 90 секунд. Я также пробовал с "GROUP BY улица", никаких преимуществ. Однако, если я добавлю .. LIMIT 3000, результат мгновенный. Я полагаю, что запрос должен перемещаться по всей таблице, чтобы получить значения DISTINCT, что не относится к LIMIT, возможно ли это из-за INDEX? Как узнать, работает ли индекс? Еще раз спасибо!

...