Saya menjalankan 350GB
database pada PC saya dengan ~ 40 juta baris.
SQL Server 2014, Win7, AMD 8350 @ 4.8GHZ, RAM 16 GB, dan SSD 500 GB (basis data di-host pada SSD 500 GB miliknya sendiri, dengan throughput 500MB / 500MB baca / tulis).
Basis data tidak diperbarui, saya hanya menganalisis / membacanya. Dengan pembuatan beberapa indexes
, apa saja join
, count(*)
dll, membutuhkan waktu kurang dari 1 menit, yang ok untuk tujuan saya. Saya telah menjalankan beberapa pertanyaan (setelah menjalankan satu permintaan bergabung, 40-50 kali, menjadi lambat) pada data, dan sekarang panggilan yang membutuhkan waktu 1 menit, masih berjalan 20 menit kemudian.
Saya mengawasi sumber daya sistem dengan hati-hati, dan saya dapat melihat SSD
tendangan ketika kueri dimulai, ia membaca selama 20-30 detik, kemudian membaca 121kB/second
selama 20 menit berikutnya. Ini bukan masalah CPU, atau masalah disk. Saya terbatas dengan jumlah RAM saya, namun panggilan berjalan dengan baik ketika saya pertama kali memuat database, sekarang, tidak ada yang berjalan, 25 menit kemudian.
Secara efektif saya tidak bisa lagi meminta basis data, panggilan apa pun butuh waktu terlalu lama bahkan SELECT
pernyataan dasar . Saya telah mencoba membangun kembali indeks dan memperbarui statistik, tetapi tidak ada perbedaan.
Saya tidak memiliki banyak pengalaman dalam hal ini sehingga sangat mungkin bahwa permintaan SQL saya salah, dalam hal ini saya mengharapkan kesalahan, atau untuk itu menyelesaikan eksekusi dengan hasil 0, tetapi tidak terjadi.
Apa yang saya coba lakukan adalah menghitung semua instance dari 'TypeID', dalam 5 detik sebelum waktu berdasarkan tabel ACALLS.
SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR, ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)
WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime
sp_whoisactive
: tautanJawaban:
Anda memiliki permintaan non-SARGable - bahkan jika Anda memiliki indeks yang baik, Anda tidak menggunakannya dengan permintaan itu.
Pertama, reaksi spontan terhadap pageiolatch_sh adalah membaca halaman dari disk ke buffer; Anda tidak memiliki RAM yang cukup untuk data yang ingin ditariknya.
Kedua, Anda perlu melihat rencana eksekusi dan penggunaan indeks - atau ketiadaannya.
Berhenti menggunakan fungsi di join Anda dan WHERE Anda, dan hanya dapatkan data yang benar-benar Anda perlukan untuk memulainya.
"ANTARA ACALLS.StartTime dan DATEADD (ss, -5, ACALLS.StartTime)" - singkirkan DATEADD di BETWEEN.
WHERE DATEPART (jam, MainView.TimeStamp) ANTARA 10 dan 13 dan CAST (MainView.TimeStamp sebagai tanggal) = '2015-12-09'
hal yang sama - singkirkan CAST - ubah '2015-12-09' menjadi satu atau dua @parameter dari tipe data yang tepat untuk MainView.TimeStamp> = @StartTimestamp DAN MainView.TimeStamp <@EndTimestamp
dan singkirkan DATEPART itu dengan membatasi @StartTimestamp dan @EndTimestamp untuk memasukkan kriteria jam Anda juga.
Mungkin memuat tabel #temp hanya dengan kunci primer / unik dari baris yang memenuhi kriteria MainView sebelum bergabung.
Hmm ... juga, jika Mainview adalah tampilan yang kompleks, langsung ke tabel dasar untuk memuat tabel #temp itu
Jangan lupa untuk menggunakan Profiler untuk memeriksa dan melihat apakah menambahkan (gabungan jika perlu) indeks pada #temp atau tabel pementasan lainnya adalah keuntungan bersih atau rugi bersih :).
sumber
buat indeks non clustered komposit pada mainview (typeid, timestamp).
ubah "where" Anda di mainview sehingga Anda tidak menggunakan fungsi melawan kolom mainview. ini mungkin mengharuskan Anda untuk menghitung ulang nilai-nilai ini sebagai variabel sebelum menjalankan kueri jika Anda ingin ini lebih dinamis.
buat indeks nonclustered pada ACALLS.StartTime.
ubah join menjadi ACALLS menjadi
dari pemahaman saya, itu akan menangani logika Anda dan bergabung dengan kinerja yang cukup tinggi dan membuat Anda menjauh dari IO.
tebakan terbaik saya tentang apa yang Anda hadapi adalah bahwa data Anda sedang dihapus dari cache dan / atau tempdb tumpah ke disk setiap saat, jadi solusi terbaik yang biasanya saya temukan adalah menulis pertanyaan lebih baik untuk hanya batasi tempdb dan penggunaan memori dan masalah yang mendasarinya hilang.
sumber