Tengo una implementación bastante básica de un servicio de carga de imágenes, donde puede cargar imágenes y etiquetarlas. Este es mi esquema:Eliminar un árbol temporal B Ordenar de una consulta SQLite
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);
e índices
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);
La razón por la que hay campos pid_high/pid_low en lugar de la clave principal norma es porque este servicio utiliza los GUID de 128 bits cliente-autorizada, pero esto no afecta significativamente la velocidad de consulta.
Dado que se trata de Internet, la gran mayoría de las imágenes de este servicio son gatos y están etiquetadas con 'gato'. De hecho, aproximadamente 47,000 de 50,000 imágenes están etiquetadas con 'gato'. La consulta para obtener todas las imágenes con la etiqueta de 'gato' es
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;
el plan de consulta para esto es
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
El problema principal aquí es la última fila, USO TEMP B-ÁRBOL DE ORDEN POR. Esto ralentiza la consulta significativamente. Sin la cláusula 'ordenar por', toda la consulta tarda alrededor de 0.001 segundos en ejecutarse. Con la cláusula order by, la consulta requiere 0.483s, que es una penalización de rendimiento de 400x.
Me gustaría obtener esta consulta en menos de 0.1 segundos, pero no estoy seguro de cómo. He intentado muchas otras consultas y agregado y eliminado índices, pero este es el más rápido que he podido ejecutar.
... resistiendo el impulso de etiquetar la pregunta con 'cat'. En serio, sin embargo, buen trabajo en la pregunta, muy detallado. – bernie
He eliminado mi respuesta, ya que no iría a ningún lado. Si encuentras una manera de resolverlo, me gustaría que lo publicaras aquí y @mencioname para que pueda echarle un vistazo. – Tomalak
@Tomalak: aquí hay una respuesta. – Quassnoi