2015-07-21 3 views
0

У меня есть база данных SQLite как часть приложения iOS, которая работает отлично по большей части, но некоторые небольшие изменения в запросе могут привести к тому, что она займет 1000 раз дольше. Вот 2 таблицы, которые я задействовал:Производительность запросов Bad SQLite с внешними соединениями

create table "journey_item" ("id" SERIAL NOT NULL PRIMARY KEY, 
"position" INTEGER NOT NULL, 
"last_update" BIGINT NOT NULL, 
"rank" DOUBLE PRECISION NOT NULL, 
"skipped" BOOLEAN NOT NULL, 
"item_id" INTEGER NOT NULL, 
"journey_id" INTEGER NOT NULL); 

create table "content_items" ("id" SERIAL NOT NULL PRIMARY KEY, 
"full_id" VARCHAR(32) NOT NULL, 
"title" VARCHAR(508), 
"timestamp" BIGINT NOT NULL, 
"item_size" INTEGER NOT NULL, 
"http_link" VARCHAR(254), 
"local_url" VARCHAR(254), 
"creator_id" INTEGER NOT NULL, 
"from_id" INTEGER,"location_id" INTEGER); 

Таблицы имеют указатели на первичные и внешние ключи.

И вот 2 запросы, которые дают хороший пример моей проблемы

SELECT * FROM content_items ci 
INNER JOIN journey_item ji ON ji.item_id = ci.id WHERE ji.journey_id = 1 

SELECT * FROM content_items ci 
LEFT OUTER JOIN journey_item ji ON ji.item_id = ci.id WHERE ji.journey_id = 1 

Первый запрос занимает 167 мс, чтобы закончить, а второй занимает 3,5 минуты, и я не знаю, почему внешнее соединение будет сделать такая огромная разница.

Edit: Без WHERE части второй запрос только занимает 267 мс

+0

Используйте [EXPLAIN] (https://www.sqlite.org/lang_explain.html), чтобы получить план выполнения. – cha

+0

@cha Я просмотрел ОБЪЯСНУЮ ПЛАН ЗАПРОСА. Второй имеет SCAN из content_items, а затем SEARCH of travel_item, который я ожидаю. Я не уверен, как читать результаты от EXPLAIN. Есть несколько дополнительных кодов операций NE, но я не знаю, почему это так сильно изменило бы производительность. – skorulis

ответ

2

два запроса должны иметь один и тот же набор результатов (оговорка where превращает left join в внутреннее соединение) `. Однако SQLite, вероятно, не распознает это.

Если у вас есть индекс на journey_item(journey_id, item_id), то он будет использоваться для версии inner join. Однако вторая версия, вероятно, сканирует первую таблицу для соединения. Индекс на journey_item(item_id) поможет, но, вероятно, все еще не соответствует производительности первого запроса.

+0

У меня были отдельные индексы во всех столбцах моего id и внешнего ключа, но у меня нет индексов нескольких столбцов. Я просто добавил travel_item (travel_id, item_id), который, казалось, исправить проблему (но мне нужно сделать еще несколько тестов). Нужно ли мне, по сути, много индексов столбцов, где я буду использовать оба запроса? – skorulis

+0

@skorulis. , , Индекс на 'journalet_item (travel_id)' также будет большой помощью для первого запроса. –

+0

Это внешний ключ, поэтому у меня уже есть указатель. – skorulis

Смежные вопросы