Pemula postgres di sini.
Saya ingin tahu apakah kueri ini dioptimalkan atau tidak? Saya mencoba untuk BERGABUNG PADA hanya nilai-nilai yang diperlukan 100% dan meninggalkan semua kondisi dinamis dalam klausa WHERE. Lihat di bawah.
SELECT *
FROM
myapp_employees
JOIN myapp_users ON
myapp_users.user_id=myapp_employees.user_id
JOIN myapp_contacts_assoc ON
myapp_contacts_assoc.user_id=myapp_users.user_id
JOIN myapp_contacts ON
myapp_contacts.contact_id=myapp_contacts_assoc.contact_id
WHERE
myapp_contacts.value='[email protected]' AND
myapp_contacts.type=(1)::INT2 AND
myapp_contacts.is_primary=(1)::INT2 AND
myapp_contacts.expired_at IS NULL AND
myapp_employees.status=(1)::INT2 AND
myapp_users.status=(1)::INT2
LIMIT 1;
Catatan: Untuk konteks, proc ini memeriksa untuk melihat apakah pengguna juga seorang karyawan (privs tinggi / tipe pengguna berbeda).
Ngomong-ngomong, apakah ini cara yang benar untuk pergi? Haruskah BERGABUNG DENGAN berisi lebih banyak pernyataan seperti memeriksa untuk expired_at IS NULL, misalnya? Mengapa atau mengapa ini tidak masuk akal?
SELECT version();
)Jawaban:
Secara logis , tidak ada bedanya sama sekali apakah Anda menempatkan kondisi dalam klausa gabungan dari
INNER JOIN
atauWHERE
klausa yang samaSELECT
. Efeknya sama.(Bukan kasus untuk
OUTER JOIN
!)Saat beroperasi dengan pengaturan default, itu juga tidak membuat perbedaan untuk rencana kueri atau kinerja . Postgres bebas mengatur ulang gabungan dan
JOIN
&WHERE
kondisi dalam pencariannya untuk rencana kueri terbaik - selama jumlah tabel tidak lebih besar darijoin_collapse_limit
(default8
). Detail:Untuk keterbacaan dan pemeliharaan , masuk akal untuk menempatkan kondisi yang menghubungkan tabel di masing-masing
JOIN
klausa dan kondisi umum dalamWHERE
klausa.Permintaan Anda terlihat baik-baik saja. Saya akan menggunakan alias tabel untuk mengurangi kebisingan.
Detail kecil:
int2 '1'
atau bahkan1::int2
lebih masuk akal daripada(1)::INT2
. Dan sementara membandingkan dengan nilai tipe data numerik yang terdefinisi dengan baik, konstanta numerik biasa1
juga cukup baik.sumber
Beberapa poin ..
Jika Anda bergabung dengan kondisi dengan nama yang sama (
user_id
) dalam kasus Anda, Anda dapat menggunakanUSING (user_id)
daripadaON (a.user_id = b.user_id)
. Ini juga menyimpan kolom redundan yang berpotensi dikeluarkan (jika Anda menjalankanSELECT *
produksi).1::int2
bermasalah. Baikstatus
, danis_primary
dan lain-lain sudahint2
dalam hal ini literal 1 akan secara otomatis dilemparkan ke int2, atau int2 dilemparkan ke int seperti pg yang cocok. Atau, jika Anda menyimpannya sebagai int reguler, dan membuangnya seolah-olah itu membuat perbedaan dalam perhitungan - yang tidak, para pemeran saja yang membuat proposisi yang hilang.Jika memungkinkan, semua :: int2 mungkin harus disimpan sebagai
boolean
. Maka Anda dapat menulisWHERE
kondisi Anda menjadi lebih sederhana juga.Untuk jenis dan status Anda, Anda mungkin menginginkan suatu
ENUM
jenis.sumber