Kueri tidak sama persis
Untuk memperjelas konteksnya:
max(id)
tidak termasukNULL
nilai-nilai. TapiORDER BY ... LIMIT 1
tidak.NULL
nilai mengurutkan terakhir dalam urutan menaik, dan pertama dalam menurun. JadiIndex Scan Backward
mungkin tidak menemukan nilai terbesar (menurutmax()
) pertama, tetapi sejumlahNULL
nilai.
Persamaan formal dari:
SELECT max(id) FROM testview;
bukan:
SELECT id FROM testview ORDER BY id DESC LIMIT 1;
tapi:
SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;
Kueri terakhir tidak mendapatkan paket kueri cepat. Tapi itu akan dengan indeks dengan urutan pengurutan yang cocok:(id DESC NULLS LAST)
.
Itu berbeda untuk fungsi agregat min()
dan max()
. Mereka mendapatkan paket cepat saat menargetkan tabel test1
langsung menggunakan indeks PK biasa di (id)
. Tetapi tidak jika berdasarkan tampilan (atau kueri gabungan yang mendasarinya secara langsung - tampilan bukanlah pemblokir). Pengurutan indeks nilai NULL di tempat yang tepat hampir tidak berpengaruh.
Kami ketahuilah bahwa id
dalam kueri ini tidak akan pernah bisa NULL
. Kolom didefinisikan NOT NULL
. Dan gabungan dalam tampilan secara efektif merupakan INNER JOIN
yang tidak dapat memperkenalkan NULL
nilai untuk id
.
Kami ketahui juga bahwa indeks pada test.id
tidak dapat berisi nilai NULL.
Tetapi perencana kueri Postgres bukanlah AI. (Tidak juga, itu bisa lepas kendali dengan cepat.) Saya melihat dua kekurangan :
min()
danmax()
dapatkan paket cepat hanya ketika menargetkan tabel, terlepas dari urutan pengurutan indeks, kondisi indeks ditambahkan:Index Cond: (id IS NOT NULL)
ORDER BY ... LIMIT 1
dapatkan paket cepat hanya dengan urutan pengurutan indeks yang sama persis.
Tidak yakin, apakah itu dapat ditingkatkan (dengan mudah).
db<>fiddle di sini - mendemonstrasikan semua hal di atas
Indeks
Indeks ini sama sekali tidak berguna:
CREATE INDEX ON "test" ("id");
PK di test.id
diimplementasikan dengan indeks unik pada kolom, yang sudah mencakup semua yang mungkin dilakukan indeks tambahan untuk Anda.
Mungkin masih ada lagi, menunggu pertanyaan selesai.
Kasus uji terdistorsi
Kasus uji terlalu jauh dari kasus penggunaan yang sebenarnya untuk menjadi bermakna.
Dalam pengaturan pengujian, setiap tabel memiliki 100 ribu baris, tidak ada jaminan bahwa setiap nilai dalam joincol
memiliki kecocokan di sisi lain, dan kedua kolom bisa NULL
Kasing asli Anda memiliki 10 juta baris di table1
dan <100 baris di table2
, setiap nilai dalam table1.joincol
memiliki kecocokan di table2.joincol
, keduanya didefinisikan NOT NULL
, dan table2.joincol
unik. Hubungan klasik satu-ke-banyak. Harus ada UNIQUE
batasan pada table2.joincol
dan batasan FK t1.joincol --> t2.joincol
.
Tapi itu saat ini semua terpelintir dalam pertanyaan. Berdiri sampai itu dibersihkan.