Saya mencoba membuat indeks di SQLite3
(3.18) menggunakan json_extract
ekspresi. Tujuan saya adalah menjalankan kueri yang hanya memerlukan indeks untuk menghasilkan hasil. Alasannya adalah karena json_extract
ini merupakan operasi yang mahal yang akan menghambat kinerja saat beroperasi pada kumpulan data dan / atau nilai yang lebih besar. Saya menyimpulkan saya perlu indeks penutup yang sesuai dengan kebutuhan saya.
Langkah 1 - Menguji teori menggunakan struktur tabel normal
CREATE TABLE Player (
Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
FirstName TEXT NOT NULL,
MiddleName TEXT,
LastName TEXT NOT NULL
);
CREATE INDEX Player_FirstName ON Player (
FirstName ASC,
LastName ASC
);
EXPLAIN QUERY PLAN SELECT
FirstName, LastName
FROM
Player
WHERE
LENGTH(LastName) > 10
ORDER BY
FirstName
LIMIT
10
OFFSET
0
Hasil
SCAN TABLE Player USING COVERING INDEX Player_FirstName
Inilah yang saya harapkan. Perencana kueri memperkirakan bahwa Player_FirstName
indeks tersebut sesuai karena ORDER BY
klausa, dan karena WHERE
pernyataan itu hanya beroperasi pada nilai yang juga ada dalam indeks itu, ia tidak perlu membaca tabel. Akhirnya, SELECT
pernyataan hanya menyertakan kolom yang diindeks karena itu menghasilkan permintaan yang tidak menyentuh tabel sama sekali .
Langkah 2 - Menguji teori dengan ekspresi ekstrak
CREATE TABLE PlayerJ (
Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
Data TEXT NOT NULL
);
CREATE INDEX PlayerJ_FirstName ON PlayerJ (
JSON_EXTRACT(Data, '$.FirstName') ASC,
JSON_EXTRACT(Data, '$.LastName') ASC
);
EXPLAIN QUERY PLAN SELECT
JSON_EXTRACT(Data, '$.FirstName') AS FirstName,
JSON_EXTRACT(Data, '$.LastName') AS LastName
FROM
PlayerJ
WHERE
LENGTH(LastName) > 10
ORDER BY
FirstName
LIMIT
10
OFFSET
0
Hasil
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Ini bukan yang saya harapkan. Perencana kueri tampaknya telah mengetahui bahwa ORDER BY
klausa aktif JSON_EXTRACT(Data, '$.FirstName')
, dan dengan demikian tampaknya telah memilih indeks yang sesuai. Tapi di situlah alasan saya berakhir dengan tiba-tiba. Apa yang terjadi disini? Saya berharap perencana kueri mengetahui bahwa ini sama dengan tes sebelumnya, dan indeks akan digunakan sebagai indeks penutup. Tapi ternyata tidak.
Kenapa tidak? Dan bagaimana tes kedua ini dapat dimodifikasi sehingga hanya berjalan terhadap indeks?
sumber