Kueri tidak sama persis
Untuk memperjelas konteksnya:
max(id)tidak termasukNULLnilai-nilai. TapiORDER BY ... LIMIT 1tidak.NULLnilai mengurutkan terakhir dalam urutan menaik, dan pertama dalam menurun. JadiIndex Scan Backwardmungkin tidak menemukan nilai terbesar (menurutmax()) pertama, tetapi sejumlahNULLnilai.
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 1dapatkan 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.