Kami memiliki gudang data dengan jumlah catatan yang cukup besar (10-20 juta baris) dan sering menjalankan kueri yang menghitung catatan antara tanggal tertentu, atau menghitung catatan dengan bendera tertentu, misalnya
SELECT
f.IsFoo,
COUNT(*) AS WidgetCount
FROM Widgets AS w
JOIN Flags AS f
ON f.FlagId = w.FlagId
WHERE w.Date >= @startDate
GROUP BY f.IsFoo
Performanya tidak buruk, tetapi bisa relatif lamban (mungkin 10 detik pada cache dingin).
Baru-baru ini saya menemukan bahwa saya dapat menggunakan GROUP BY
dalam tampilan yang diindeks dan mencoba sesuatu yang mirip dengan yang berikut ini
CREATE VIEW TestView
WITH SCHEMABINDING
AS
SELECT
Date,
FlagId,
COUNT_BIG(*) AS WidgetCount
FROM Widgets
GROUP BY Date, FlagId;
GO
CREATE UNIQUE CLUSTERED INDEX PK_TestView ON TestView
(
Date,
FlagId
);
Akibatnya kinerja kueri pertama saya sekarang <100 ms, dan tampilan & indeks yang dihasilkan adalah <100rb (meskipun jumlah baris kami besar, kisaran tanggal dan ID bendera berarti bahwa tampilan ini hanya berisi 1000-2000 baris).
Saya berpikir bahwa mungkin ini akan melumpuhkan kinerja menulis ke tabel Widget, tetapi tidak - kinerja menyisipkan dan pembaruan ke dalam tabel ini cukup banyak yang tidak terpengaruh sejauh yang saya tahu (ditambah, menjadi gudang data, tabel ini diperbarui jarang. bagaimanapun)
Bagi saya, ini kelihatannya terlalu bagus untuk menjadi kenyataan - bukan? Apa yang harus saya perhatikan saat menggunakan tampilan yang diindeks dengan cara ini?
SELECT
danCREATE VIEW
salah, karena saya percayaCREATE INDEX
skrip Anda .Jawaban:
Seperti yang telah Anda catat, tampilan itu sendiri mematerialisasi sejumlah kecil baris - jadi meskipun Anda memperbarui seluruh tabel, tambahannya I / O yang terlibat dengan memperbarui tampilan diabaikan. Anda mungkin sudah merasakan sakit terbesar yang akan Anda rasakan ketika Anda menciptakan pemandangan itu. Yang terdekat berikutnya adalah jika Anda menambahkan trilyun baris ke tabel dasar dengan sekelompok ID baru yang membutuhkan baris baru dalam tampilan.
Ini tidak terlalu bagus untuk menjadi kenyataan. Anda menggunakan tampilan yang diindeks dengan tepat bagaimana mereka seharusnya digunakan - atau setidaknya salah satu cara yang paling efektif: untuk membayar agregasi permintaan di masa mendatang pada saat penulisan. Ini bekerja paling baik ketika hasilnya jauh lebih kecil dari sumber dan tentu saja ketika agregasi diminta lebih sering daripada data dasar diperbarui (lebih umum di DW daripada OLTP, umumnya).
Sayangnya banyak orang berpikir bahwa pengindeksan tampilan adalah sihir - indeks tidak akan membuat semua tampilan lebih efisien, terutama tampilan yang hanya bergabung dengan tabel dan / atau menghasilkan jumlah baris yang sama dengan sumbernya (atau bahkan berlipat ganda). Dalam kasus ini, I / O dari tampilan adalah sama atau bahkan lebih buruk dari permintaan asli, tidak hanya karena ada baris yang sama atau lebih, tetapi seringkali mereka menyimpan dan mematerialisasi lebih banyak kolom juga. Jadi mematerialisasikan mereka di muka tidak memberikan keuntungan apa pun, karena - bahkan dengan SSD - I / O, jaringan, dan pemrosesan / rendering klien masih tetap menjadi hambatan utama dalam mengembalikan hasil yang besar kepada klien. Penghematan yang Anda dapatkan dalam menghindari bergabung saat runtime tidak dapat diukur dibandingkan dengan semua sumber daya lain yang masih Anda gunakan.
Seperti indeks yang tidak berkerumun, berhati-hatilah untuk tidak melakukannya secara berlebihan. Jika Anda menambahkan 10 tampilan indeks yang berbeda ke satu tabel, Anda akan melihat lebih banyak dampak pada bagian tulis dari beban kerja Anda, terutama jika kolom pengelompokan bukan kunci pengelompokan.
Astaga, saya sudah bermaksud untuk blog tentang topik ini.
sumber
Aarons menjawab pertanyaan ini dengan baik. Dua hal untuk ditambahkan:
Saya telah menggunakan agregasi dan menggabungkan pandangan dengan manfaat ekstrem.
Semua dalam semua kasus penggunaan Anda sepertinya kasus yang sempurna. Pandangan terindeks adalah teknik yang jauh kurang dimanfaatkan.
sumber