Utilizzando un ordine, SQLite esegue la scansione dell'intera tabella e carica tutti i valori in un b-tree temporaneo per ordinarli, rendendo inutile qualsiasi indice. Questo sarà molto lento e utilizzare un sacco di memoria su grandi tavoli:
explain query plan select * from 'table' order by abs(10 - value) limit 1;
0|0|0|SCAN TABLE table
0|0|0|USE TEMP B-TREE FOR ORDER BY
È possibile ottenere il valore successivo inferiore o superiore utilizzando l'indice in questo modo:
select min(value) from 'table' where x >= N;
select max(value) from 'table' where x <= N;
Ed è possibile utilizzare union
per ottenere entrambi da una singola query:
explain query plan
select min(value) from 'table' where value >= 10
union select max(value) from 'table' where value <= 10;
1|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>?)
2|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value<?)
0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
Questo sarà abbastanza veloce anche su tavoli di grandi dimensioni. Si potrebbe semplicemente caricare entrambi i valori e valutarli nel codice, o utilizzare anche più di SQL per selezionare uno in vari modi:
explain query plan select v from
( select min(value) as v from 'table' where value >= 10
union select max(value) as v from 'table' where value <= 10)
order by abs(10-v) limit 1;
2|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>?)
3|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value<?)
1|0|0|COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)
0|0|0|SCAN SUBQUERY 1
0|0|0|USE TEMP B-TREE FOR ORDER BY
o
explain query plan select 10+v from
( select min(value)-10 as v from 'table' where value >= 10
union select max(value)-10 as v from 'table' where value <= 10)
group by v having max(abs(v)) limit 1;
2|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>?)
3|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value<?)
1|0|0|COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)
0|0|0|SCAN SUBQUERY 1
0|0|0|USE TEMP B-TREE FOR GROUP BY
Dal momento che siete interessati a entrambi i valori arbitrariamente grandi e meno del target, non puoi evitare di fare due ricerche su indici. Se si sa che il bersaglio è all'interno di un piccolo intervallo, però, è possibile utilizzare "tra" a colpire solo l'indice una volta:
explain query plan select * from 'table' where value between 9 and 11 order by abs(10-value) limit 1;
0|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>? AND value<?)
0|0|0|USE TEMP B-TREE FOR ORDER BY
Questo si aggirano intorno a 2 volte più veloce rispetto alla query di unione di cui sopra quando si valuta solo 1 -2 valori, ma se si inizia a dover caricare più dati diventerà rapidamente più lento.
Ricordare che il sistema di tipo sqlite è speciale e se si dispone di un vero doppio non ha nulla a che fare con dichiarazioni di tipo. – unmounted