SQL Server 2014 Tiba-tiba Melambat / Tidak ada sisipan / Tidak terkait dengan perangkat keras atau indeks

8

Saya menjalankan 350GBdatabase 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 SSDtendangan ketika kueri dimulai, ia membaca selama 20-30 detik, kemudian membaca 121kB/secondselama 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 SELECTpernyataan 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

Setelah menjalankan "Who is Running", masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini


sumber
Saya menduga ini ada hubungannya dengan statistik pada tabel dan jenis pengolahan yang dilakukan untuk bergabung. Anda harus melihat rencana eksekusi untuk kueri: nested loop joins bisa menjadi tanda masalah.
Gordon Linoff
Sudahkah Anda mencoba DENGAN RECOMPILE?
3
Posting rencana eksekusi aktual dari permintaan yang sangat lambat. Semakin sederhana kueri, semakin baik.
usr
1
Sudahkah Anda memperbarui statistik di semua tabel? Sudahkah Anda membangun kembali semua indeks? Informasi tentang sp_whoisactive: tautan
TT.
2
Statistik penantian itu menunjukkan banyak IO tetapi kami tidak tahu proporsi kueri apa itu IO dan apa itu CPU. Lakukan tes yang saya rekomendasikan sebagai hasil posting.
usr

Jawaban:

2

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.

    • Jika ini hanya baca, database pelaporan, kemudian buat tabel pelaporan hanya dengan data yang Anda butuhkan, dan kemudian letakkan indeks gabungan di atasnya sesuai kebutuhan. Gunakan yang itu untuk mendapatkan kunci utama / kunci unik lainnya dari baris ACALLS yang Anda butuhkan, kemudian dapatkan sisa data ACALLS nanti.
  • 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 :).

Kata sandi yang lemah
sumber
1

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.

WHERE MainView.TimeStamp BETWEEN '2015-12-09 10:00' and '2015-12-09 13:00'

buat indeks nonclustered pada ACALLS.StartTime.

ubah join menjadi ACALLS menjadi

WHERE ACALLS.StartTime BETWEEN DATEADD(ss,-5,MainView.TimeStamp) AND MainView.TimeStamp

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.

Bruce Dunwiddie
sumber