Tiga tabel:
product
: dengan kolom: ( a, g, ...a_lot_more... )
a: PK, clustered
g: bit-column
main
: dengan kolom: ( c, f, a, b, ...a_lot_more... )
c: PK, clustered
f: bit-column
(a, b): UQ
lookup
dengan kolom: ( a, b, c, i )
(a, b): PK, clustered
a: FK to product(a)
c: UQ, FK to main(c)
i: bit-column
Saya tidak dapat menemukan indeks yang baik untuk bergabung:
FROM
product
JOIN
lookup
ON lookup.a = product.a
JOIN
main
ON main.c = lookup.c
WHERE
product.g = 1
AND
main.f = 1
AND
lookup.i = 1
AND lookup.b = 17
Saya mencoba indeks penutup product (g, a, ...)
dan itu digunakan tetapi tidak dengan hasil yang spektakuler.
Beberapa kombinasi indeks di atas lookup
meja menghasilkan rencana eksekusi dengan gabungan indeks, dengan sedikit peningkatan efisiensi dibandingkan rencana sebelumnya.
Apakah ada kombinasi jelas yang saya lewatkan?
Bisakah desain ulang struktur membantu?
DBMS adalah MySQL 5.5 dan semua tabel menggunakan InnoDB.
Ukuran meja:
product: 67K , g applied: 64K
main: 420K , f applied: 190K
lookup: 12M , b,i applied: 67K
mysql
mysql-5.5
optimization
ypercubeᵀᴹ
sumber
sumber
Jawaban:
Ini menyakitkan saya ...
Saya harus menggunakan tabel temp dengan InnoDB sebelumnya. Muat dengan filter, buat indeks, gabungkan tabel temp ini.
Masalahnya menurut saya adalah jika InnoDB itu hanya memiliki algoritma Nested Join: pengoptimal permintaan RDBMS dewasa memiliki lebih banyak untuk digunakan. Ini didasarkan pada upaya untuk menjalankan beban tipe Gudang Data di InnoDB.
Tabel temp menyeret keseluruhan kompleksitas ke tingkat pengoptimal permintaan MySQL ...
sumber
main
) dengan mendenormalisasi datalookup
?Itu terlihat seperti produk Cartesian. Ulangi Kriteria GABUNG
ALTERNASI SARAN
Ini mungkin tampak tidak lazim dan mungkin berbau seperti SQL Anitpattern, tapi ini dia ...
Saya tidak memindahkan
product.g = 1
danmain.f = 1
ke subqueries karena mereka adalah bidang bit dan hanya akan melakukan pemindaian tabel pada saat itu. Bahkan jika bidang bit adalah indeks, Pengoptimal Permintaan akan mengabaikan indeks seperti itu.Tentu saja, Anda bisa berubah
SELECT * FROM lookup
menjadiSELECT a FROM lookup
jika SELECT Anda tidak membutuhkan apa pun darinyalookup
Mungkin melibatkan a, b dalam GABUNGAN antara pencarian dan main jika ini masuk akal
atau masukkan kembali c dan gabung di tiga kolom (Indeks pada tiga kolom di
main
danlookup
)sumber
main.f
danproduct.g
??? Jika kardinalitasmain.f
danproduct.g
untuk nilainya adalah 1 kurang dari 5% dari baris tabel, indeks aktifmain.f
danproduct.g
dapat dibenarkan.main.f
danproduct.g
2, Anda bisa membuang indeks tersebut.