tl;dr Anda perlu menambahkan indeks pada item_id
. "Sihir hitam" dari pengindeksan Postgres tercakup dalam 11. Indeks
.
Anda memiliki indeks gabungan di (topic_id, item_id)
dan urutan kolom adalah penting. Postgres dapat menggunakan ini untuk mengindeks kueri di topic_id
, kueri pada kedua topic_id
dan item_id
, tetapi tidak (atau kurang efisien) item_id
sendirian.
Dari 11.3. Indeks Multikolom ...
-- indexed
select *
from topics_items
where topic_id = ?
-- also indexed
select *
from topics_items
where topic_id = ?
and item_id = ?
-- probably not indexed
select *
from topics_items
where item_id = ?
Ini karena indeks gabungan seperti (topic_id, item_id)
menyimpan ID topik terlebih dahulu, lalu ID item yang juga memiliki ID topik tersebut. Untuk mencari ID item secara efisien dalam indeks ini, Postgres harus terlebih dahulu mempersempit pencarian dengan ID topik.
Postgres bisa membalikkan indeks jika dianggap sepadan dengan usaha. Jika ada sejumlah kecil kemungkinan ID topik, dan sejumlah besar kemungkinan ID indeks, itu akan mencari ID indeks di setiap ID topik.
Misalnya, katakanlah Anda memiliki 10 kemungkinan ID topik dan 1000 kemungkinan ID item dan (topic_id, index_id)
indeks Anda . Ini seperti memiliki 10 ember ID topik berlabel jelas masing-masing dengan 1000 ember ID item berlabel jelas di dalamnya. Untuk sampai ke ember ID item, itu harus melihat ke dalam setiap ember ID topik. Untuk menggunakan indeks ini pada where item_id = 23
Postgres harus mencari masing-masing dari 10 keranjang ID topik untuk semua keranjang dengan ID item 23.
Tetapi jika Anda memiliki 1000 kemungkinan ID topik dan 10 kemungkinan ID item, Postgres harus mencari 1000 ember ID topik. Kemungkinan besar itu akan melakukan pemindaian tabel penuh sebagai gantinya. Dalam hal ini Anda ingin membalikkan indeks Anda dan menjadikannya (item_id, topic_id)
.
Ini sangat bergantung pada statistik tabel yang baik, yang berarti memastikan autovacuum berfungsi dengan baik.
Jadi, Anda dapat menggunakan satu indeks untuk dua kolom, jika satu kolom memiliki variabilitas yang jauh lebih sedikit daripada yang lain.
Postgres juga dapat menggunakan indeks mulitple jika dianggap akan membuat kueri berjalan lebih cepat
. Misalnya, jika Anda memiliki indeks di topic_id
dan indeks pada item_id
, itu bisa gunakan kedua indeks dan gabungkan hasilnya. Misalnya where topic_id = 23 or item_id = 42
dapat menggunakan indeks topic_id untuk mencari ID topik 23, dan indeks item_id untuk mencari ID item 42, lalu menggabungkan hasilnya.
Ini biasanya lebih lambat daripada memiliki (topic_id, item_id)
composite gabungan indeks. Ini juga bisa lebih lambat daripada menggunakan indeks tunggal, jadi jangan heran jika Postgres memutuskan untuk tidak menggunakan banyak indeks.
Secara umum, untuk indeks b-tree, bila Anda memiliki dua kolom, Anda memiliki tiga kemungkinan kombinasi.
- a + b
- a
- b
Dan Anda membutuhkan dua indeks.
- (a, b) -- a dan a + b
- (b) -- b
(a, b)
mencakup kedua pencarian untuk a dan a + b. (b)
mencakup pencarian b
.
Bila Anda memiliki tiga kolom, Anda memiliki tujuh kemungkinan kombinasi.
- a + b + c
- a + b
- a + c
- a
- b + c
- b
- c
Tapi Anda hanya membutuhkan tiga indeks.
- (a, b, c) -- a, a + b, a + b + c
- (b, c) -- b, b + c
- (c, a) -- c, c + a
Namun, Anda mungkin sebenarnya ingin menghindari indeks pada tiga kolom. Seringkali lebih lambat . Apa yang sebenarnya Anda inginkan adalah ini.
- (a,b)
- (b, c)
- (c, a)
Membaca dari indeks lebih lambat daripada membaca dari tabel. Anda ingin indeks Anda mengurangi jumlah baris yang harus dibaca, tetapi Anda tidak ingin Postgres harus melakukan pemindaian indeks lebih dari yang diperlukan.