У меня есть довольно простая реализация службы загрузки изображений, где вы можете загружать изображения и отмечать их.Это моя схема:
CREATE TABLE Tag(
orm_id INTEGER PRIMARY KEY AUTOINCREMENT,
pid_high UNSIGNED BIG INT NOT NULL,
pid_low UNSIGNED BIG INT NOT NULL,
name STRING NOT NULL,
CONSTRAINT KeyConstraint UNIQUE (pid_high, pid_low) ON CONFLICT FAIL);
CREATE TABLE TagBridge(
orm_id INTEGER PRIMARY KEY AUTOINCREMENT,
pid_high UNSIGNED BIG INT NOT NULL,
pid_low UNSIGNED BIG INT NOT NULL,
image_id_high UNSIGNED BIG INT NOT NULL,
image_id_low UNSIGNED BIG INT NOT NULL,
tag_id_high UNSIGNED BIG INT NOT NULL,
tag_id_low UNSIGNED BIG INT NOT NULL,
CONSTRAINT KeyConstraint UNIQUE (pid_high, pid_low) ON CONFLICT FAIL);
CREATE TABLE Image(
orm_id INTEGER PRIMARY KEY AUTOINCREMENT,
pid_high UNSIGNED BIG INT NOT NULL,
pid_low UNSIGNED BIG INT NOT NULL,
filehash STRING NOT NULL,
mime STRING NOT NULL,
uploadedDate INTEGER NOT NULL,
ratingsAverage REAL,
CONSTRAINT KeyConstraint UNIQUE (pid_high, pid_low) ON CONFLICT FAIL);
И индексы
CREATE INDEX ImageTest on Image(pid_high, pid_low, uploadedDate DESC);
CREATE INDEX ImagefilehashIndex ON Image (filehash);
CREATE INDEX ImageuploadedDateIndex ON Image (uploadedDate);
CREATE INDEX TagnameIndex ON Tag (name);
Причина, по которой вместо стандартного первичного ключа есть поля pid_high / pid_low, заключается в том, что эта служба использует доверенный клиенту 128-битовые идентификаторы GUID, но это не оказывает существенного влияния на скорость запроса.
Поскольку это Интернет, подавляющее большинство изображений на этом сервисе - это кошки, и они помечены как «кошка».Фактически, около 47 000 из 50 000 изображений помечены как «кошка».Запрос для получения всех изображений с тегом 'cat':
select i.* from Tag t, TagBridge b, Image i
where
b.tag_id_high = t.pid_high AND b.tag_id_low = t.pid_low
AND b.image_id_high = i.pid_high and b.image_id_low = i.pid_low
AND t.name ='cat'
order by uploadedDate DESC LIMIT 20;
План запроса для этого:
sele order from deta
---- ------------- ---- ----
0 0 0 SEARCH TABLE Tag AS t USING INDEX TagnameIndex (name=?) (~1 rows)
0 1 1 SCAN TABLE TagBridge AS b (~472 rows)
0 2 2 SEARCH TABLE Image AS i USING INDEX ImageTest (pid_high=? AND pid_low=?) (~1 rows)
0 0 0 USE TEMP B-TREE FOR ORDER BY
Основная проблема здесь - последняя строка, USE TEMP B-Дерево для заказаЭто значительно замедляет запрос.Без предложения order by весь запрос выполняется примерно за 0,001 секунды.С предложением order by запрос занимает 0,483 секунды, что является 400-кратным снижением производительности.
Я бы хотел получить этот запрос менее чем за 0,1 секунды, но я не уверен, как это сделать.Я пробовал много других запросов, добавлял и удалял индексы, но это самый быстрый из тех, что мне удалось выполнить.