Saya punya pertanyaan tentang pendekatan terbaik. Saya tidak yakin pendekatan mana yang terbaik ketika data dianggap variabel dalam ukuran.
Pertimbangkan 3 TABEL berikut:
KARYAWAN
EMPLOYEE_ID, EMP_NAME
PROYEK
PROJECT_ID, PROJ_NAME
EMP_PROJ (banyak ke banyak dari dua tabel di atas)
EMPLOYEE_ID, PROJECT_ID
Masalah : Diberikan EmployeeID, temukan SEMUA karyawan dari SEMUA Proyek yang dikaitkan dengan Karyawan ini.
Saya telah mencoba ini dalam dua cara .. kedua pendekatan hanya berbeda dengan beberapa milidetik tidak peduli ukuran data apa yang digunakan.
SELECT EMP_NAME FROM EMPLOYEE
WHERE EMPLOYEE_ID IN (
SELECT EMPLOYEE_ID FROM EMP_PROJ
WHERE PROJECT_ID IN (
SELECT PROJECT_ID FROM EMP_PROJ p, EMPLOYEE e
WHERE p.EMPLOYEE_ID = E.EMPLOYEE_ID
AND E.EMPLOYEE_ID = 123)
Pergilah
select c.EMP_NAME FROM
(SELECT PROJECT_ID FROM EMP_PROJ
WHERE EMPLOYEE_ID = 123) a
JOIN
EMP_PROJ b
ON a.PROJECT_ID = b.PROJECT_ID
JOIN
EMPLOYEE c
ON b.EMPLOYEE_ID = c.EMPLOYEE_ID
Sampai sekarang, saya mengharapkan sekitar 5000 Karyawan dan Proyek masing-masing .. tetapi tidak tahu tentang apa yang ada banyak-banyak hubungan. Pendekatan mana yang akan Anda rekomendasikan? Terima kasih!
EDIT: Rencana Eksekusi Pendekatan 1
"Hash Join (cost=86.55..106.11 rows=200 width=98)"
" Hash Cond: (employee.employee_id = emp_proj.employee_id)"
" -> Seq Scan on employee (cost=0.00..16.10 rows=610 width=102)"
" -> Hash (cost=85.07..85.07 rows=118 width=4)"
" -> HashAggregate (cost=83.89..85.07 rows=118 width=4)"
" -> Hash Semi Join (cost=45.27..83.60 rows=118 width=4)"
" Hash Cond: (emp_proj.project_id = p.project_id)"
" -> Seq Scan on emp_proj (cost=0.00..31.40 rows=2140 width=8)"
" -> Hash (cost=45.13..45.13 rows=11 width=4)"
" -> Nested Loop (cost=0.00..45.13 rows=11 width=4)"
" -> Index Scan using employee_pkey on employee e (cost=0.00..8.27 rows=1 width=4)"
" Index Cond: (employee_id = 123)"
" -> Seq Scan on emp_proj p (cost=0.00..36.75 rows=11 width=8)"
" Filter: (p.employee_id = 123)"
Rencana Pelaksanaan Pendekatan 2:
"Nested Loop (cost=60.61..112.29 rows=118 width=98)"
" -> Index Scan using employee_pkey on employee e (cost=0.00..8.27 rows=1 width=4)"
" Index Cond: (employee_id = 123)"
" -> Hash Join (cost=60.61..102.84 rows=118 width=102)"
" Hash Cond: (b.employee_id = c.employee_id)"
" -> Hash Join (cost=36.89..77.49 rows=118 width=8)"
" Hash Cond: (b.project_id = p.project_id)"
" -> Seq Scan on emp_proj b (cost=0.00..31.40 rows=2140 width=8)"
" -> Hash (cost=36.75..36.75 rows=11 width=8)"
" -> Seq Scan on emp_proj p (cost=0.00..36.75 rows=11 width=8)"
" Filter: (employee_id = 123)"
" -> Hash (cost=16.10..16.10 rows=610 width=102)"
" -> Seq Scan on employee c (cost=0.00..16.10 rows=610 width=102)"
Jadi sepertinya rencana Eksekusi Pendekatan 2 sedikit lebih baik, karena 'biaya' 60 dibandingkan dengan 85 pendekatan 1. Apakah itu cara yang tepat untuk menganalisis ini?
Bagaimana orang tahu itu akan berlaku bahkan untuk semua jenis banyak-banyak kombinasi?
sumber
explain analyze
mungkin mengungkapkan lebih banyak perbedaan antara paketJawaban:
Dalam SQL Server, dengan beberapa asumsi seperti "bidang tersebut tidak dapat berisi NULLs", kueri tersebut harus memberikan rencana yang hampir sama.
Tetapi pertimbangkan juga tipe gabung yang Anda lakukan. Klausa IN seperti ini adalah Semi Gabung, bukan Gabung Dalam. Batin Gabung dapat memproyeksikan ke beberapa baris, sehingga memberikan duplikat (dibandingkan dengan menggunakan IN atau EXIS). Jadi, Anda mungkin ingin mempertimbangkan perilaku ini saat memilih cara Anda menulis kueri.
sumber
IN
danEXISTS
selalu memberikan rencana yang sama dalam pengalaman saya.NOT IN
danNOT EXISTS
berbeda namun dengan yangNOT EXISTS
disukai - Beberapa perbandingan kinerja di siniApa yang dicari oleh kueri Anda adalah adil
atau
sumber
SELECT 1
bukanSELECT *
?Anda dapat mencoba pertanyaan ini:
sumber