Bagaimana cara membuat pandangan serikat bekerja lebih efisien?

8

Saya memiliki tabel besar (puluhan hingga ratusan juta rekaman) yang kami bagi karena alasan kinerja menjadi tabel aktif dan arsip, menggunakan pemetaan lapangan langsung, dan menjalankan proses arsip setiap malam.

Di beberapa tempat dalam kode kami, kami perlu menjalankan kueri yang menggabungkan tabel aktif dan arsip, hampir selalu difilter oleh satu atau beberapa bidang (yang kami jelaskan menempatkan indeks di kedua tabel). Untuk kenyamanan, masuk akal untuk memiliki tampilan seperti ini:

create view vMyTable_Combined as
select * from MyTable_Active
union all
select * from MyTable_Archive

Tetapi jika saya menjalankan query seperti

select * from vMyTable_Combined where IndexedField = @val

itu akan melakukan penyatuan pada segala sesuatu dari Active dan Store sebelum difilter @val, yang akan mematikan kinerja.

Apakah ada cara cerdas untuk membuat dua sub-kueri dari gabungan melihat setiap filter @valsebelum mereka membuat gabungan?

Atau mungkin ada beberapa pendekatan lain yang Anda sarankan untuk mencapai apa yang saya tuju, yaitu cara yang mudah dan efisien untuk mendapatkan catatan serikat pekerja, difilter oleh bidang yang diindeks?

EDIT: inilah rencana eksekusi (dan Anda bisa melihat nama tabel sebenarnya di sini):

rencana eksekusi

Anehnya, tabel aktif sebenarnya menggunakan indeks yang benar (plus pencarian RID?) Tetapi tabel arsip melakukan pemindaian tabel!

Shaul Behr
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Paul White 9

Jawaban:

8

Komentar pada pertanyaan menunjukkan bahwa masalahnya adalah bahwa basis data uji yang digunakan OP untuk mengembangkan kueri memiliki karakteristik data yang sangat berbeda dari basis data produksi. Barisnya jauh lebih sedikit dan bidang yang digunakan untuk pemfilteran tidak cukup selektif.

Ketika jumlah nilai yang berbeda dalam kolom terlalu kecil indeks mungkin tidak cukup selektif. Dalam hal ini pemindaian tabel sekuensial lebih murah daripada operasi pencarian indeks / baris pencarian. Biasanya pemindaian tabel menggunakan secara ekstensif sekuensial I / O, yang jauh lebih cepat daripada akses acak.

Seringkali, jika kueri akan mengembalikan lebih dari beberapa persen baris, akan lebih murah hanya dengan melakukan pemindaian tabel daripada pencarian indeks / pencarian baris atau operasi serupa yang banyak menggunakan I / O acak.

ConcernedOfTunbridgeWells
sumber
1

Hanya untuk menambahkan, apa yang saya temukan. Jika kamu melakukan:

create view vMyTable_Combined as
select *, 1 AS [Active] from MyTable_Active
union all
select *, 0 AS [Active] from MyTable_Archive

Kemudian Anda dapat memfilter pada bidang [Aktif], dan memastikan bahwa bagian lainnya tidak dimuat.

Michael Møldrup
sumber