2016-10-24 2 views
1

Das Ausführen des folgenden Codes erstellt eine Tabelle mit zwei Spalten und fügt 1 Million Zeilen hinzu. Eine Spalte ist INT und eine ist TEXT. Dann erstellt es einen Index pro Spalte und einen collate nocase Index pro Spalte. Dann führt es drei Abfragen aus.Sqlite verwendet keine Indizes

Die erste Abfrage verwendet den Index t2 wie erwartet.

Die zweite Abfrage ist die gleiche wie die erste Abfrage, fügt jedoch die ESCAPE-Klausel hinzu und verwendet den Index nicht. Das Vorhandensein von unescaped % oder _ sollte verhindern, dass der Index (vollständig) verwendet wird, aber das Vorhandensein der ESCAPE Klausel selbst sollte nicht.

Warum verhindert die Klausel ESCAPE, dass der Index verwendet wird?

Die dritte Abfrage ist die gleiche wie die erste, verwendet jedoch nicht den Index. Der einzige Unterschied besteht darin, dass die Abfrage die Spalte col_i anstelle von col_t verwendet, die als INT anstelle von TEXT definiert ist. Sqlite hindert mich nicht daran, den Index zu erstellen, also würde ich erwarten, dass er benutzt wird.

Warum wird der Index i2 nicht verwendet?

.timer on 
DROP TABLE IF EXISTS tab; 
CREATE TABLE tab (col_t TEXT, col_i INT); 
INSERT INTO tab (col_i, col_t) WITH RECURSIVE cte (x, y) AS (SELECT hex(randomblob(16)), hex(randomblob(16)) UNION ALL SELECT hex(randomblob(16)), hex(randomblob(16)) FROM cte LIMIT 1000000) SELECT x, y FROM cte; 
CREATE INDEX t ON tab (col_t); 
CREATE INDEX t2 ON tab (col_t COLLATE nocase); 
CREATE INDEX i ON tab (col_i); 
CREATE INDEX i2 ON tab (col_i COLLATE nocase); 
SELECT * FROM tab WHERE col_t LIKE 'abcabcabc'; 
SELECT * FROM tab WHERE col_t LIKE 'abcabcabc' ESCAPE '\'; 
SELECT * FROM tab WHERE col_i LIKE 'abcabcabc'; 

Antwort

2

Die documentation Dokumente, wenn der Index für LIKE verwendet werden können:

  1. Die linke Seite ... muss der Name einer indizierten Spalte mit TEXT Affinität sein.
  2. Die rechte Seite ... muss ... ein Zeichenfolgenliteral ... sein, das nicht mit einem Platzhalterzeichen beginnt.
  3. Die ESCAPE-Klausel kann nicht auf dem Operator LIKE erscheinen.
  4. Die integrierten Funktionen zum Implementieren von LIKE ... dürfen nicht mit der API sqlite3_create_function() überladen worden sein.
  5. [...]
  6. ... die Spalte muss mithilfe der integrierten NOCASE-Sortierfolge indiziert werden.

Der Abfrageoptimierer hat zu beweisen, dass der Index verwendet, kann nicht die Bedeutung der Abfrage ändern. Diese Regeln implementieren den Beweis.

Während Abfragen vorhanden sind, die trotz Verletzung dieser Regeln mit dem Index arbeiten würden, wäre es erforderlich, das Optimierungsprogramm so zu erweitern, dass bewiesen werden kann, dass sie funktionieren.

Verwandte Themen