Apakah ada cara untuk menentukan apakah query SQL Server berjalan di memori atau pergi ke disk?

13

Saya menemukan serangkaian prosedur tersimpan dalam aplikasi hari ini yang dipanggil berulang kali dalam proses yang berjalan lama. Dalam setiap prosedur saya menemukan beberapa pernyataan pilih yang berbeda, beberapa dalam loop; tidak mengherankan, rutinitas ini seperti yang digunakan saat ini membutuhkan waktu beberapa menit untuk berjalan, ketika intuisi mengharapkannya selesai dalam beberapa detik.

Tampaknya cukup jelas bahwa kinerja tidak dipertimbangkan ketika prosedur ini ditulis, ada beberapa contoh hal-hal yang "bukan ide yang baik".

Memproses setiap baris saat mengimpor data membutuhkan 300 ms per baris, sehingga impor yang relatif kecil membutuhkan waktu beberapa menit untuk diproses.

Namun, tabel yang terlibat dalam prosedur sebagian besar cukup kecil. Saya berpikir, jika semua tabel ini sepenuhnya tersimpan dalam memori, mungkin tidak banyak yang dapat diperoleh dengan menulis ulang semua ini.

Saya mencoba menentukan .... untuk kode yang jelas tidak efisien ini, seberapa besar pengaruh nyata yang dimilikinya? Apakah perlu diperbaiki?

Jadi pertanyaannya adalah:
- adakah cara untuk menentukan tabel apa yang sepenuhnya disematkan dalam memori?
- adakah cara untuk mengaktifkan penelusuran untuk memantau prosedur tersimpan yang bersarang untuk menemukan bagian yang sangat mahal?

Catatan: Ini ada di SQL Server 2008 R2

tulang T
sumber

Jawaban:

12

Anda bisa menggunakan salah satu dari dua pertanyaan ini untuk melihat total pembacaan logis dan total pembacaan fisik.

SELECT  DB_NAME(st.dbid) Db,
        OBJECT_NAME(st.objectid, st.dbid) Prc,
        qs.execution_count,
        qs.total_logical_reads,
        qs.total_physical_reads,
        qs.statement_start_offset,
        qs.statement_end_offset,
        st.text
FROM    sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st;

SELECT  DB_NAME(database_id) Db,
        OBJECT_NAME(object_id, database_id) Prc,
        execution_count,
        total_logical_reads,
        total_physical_reads
FROM    sys.dm_exec_procedure_stats ps;

Yang pertama memecah ini dengan pernyataan, yang kedua diperhitungkan dalam seluruh prosedur.

Pembacaan fisik dibaca terhadap disk, pembacaan logis terhadap memori. Anda dapat menggunakan ini untuk mencari tahu prosedur atau pernyataan mana yang paling mahal di sistem Anda dan mencoba menyetelnya.

Perlu diingat, bahwa sementara pembacaan logis secara signifikan lebih murah daripada pembacaan fisik, mereka masih mahal, sehingga mengurangi jumlah mereka (misalnya dengan menambahkan indeks yang sesuai) dapat membuat kueri Anda berjalan jauh lebih cepat.

Ada banyak kolom tambahan dalam DMV di atas yang mungkin Anda temukan menarik juga.


Bagaimana indeks membantu mengurangi pembacaan logis?

Dalam SQL Server semua data diatur dalam blok, berukuran 8KB. Blok ini disebut "halaman".

Setiap tabel berisi halaman "meta" yang berisi informasi tentang struktur tabel serta halaman pata. Jika tidak ada indeks dan Anda menjalankan kueri seperti SELECT * FROM tbl WHERE Id = 7SQL Server harus mencari ini atau ini baris di seluruh tabel. Jadi bunyinya dalam satu halaman pada satu waktu, loop melalui semua baris di setiap halaman untuk menentukan baris yang sesuai dengan WHEREklausa. Jadi, jika tabel membutuhkan 1.000.000 halaman untuk disimpan, kueri ini akan mengambil 1.000.000 bacaan logis untuk dieksekusi.

Jika Anda memiliki indeks, SQL Server mengurutkan data secara logis di dalam halaman dan membuat daftar tertaut di antara halaman. Ini memungkinkan untuk menjalankan kueri dengan ORDER BYeksekusi tanpa operasi sortir yang mahal. Tetapi lebih penting lagi bahwa penyortiran, SQL Server menambahkan B + Tree ke tabel. B + Tree adalah struktur yang sebanding dengan indeks dalam sebuah buku, di mana mencari kata kunci tertentu memungkinkan saya untuk langsung melompat ke halaman yang berisi kata kunci. Buku tipikal hanya memiliki satu level indeks sedangkan B + Tree dapat memiliki beberapa level. Bayangkan sebuah buku besar, di mana indeks itu sendiri panjangnya beberapa halaman. Dalam kasus seperti itu masuk akal menambahkan lapisan indeks tambahan yang memberitahu kita pada halaman yang kata-kata indeks dimulai dengan Sdapat ditemukan.

Pohon B + dioptimalkan untuk memiliki level sesedikit mungkin sambil memberikan properti yang setiap catatan dalam indeks dapat ditemukan dengan membaca satu halaman per level indeks. Jadi asumsikan WHERE Id = 7kueri di atas ketika Anda memiliki indeks yang diurutkan berdasarkan Id. Katakanlah indeks itu memiliki 5 level. Sekarang, untuk menemukan semua catatan yang cocok dengan kueri ini, saya harus membaca satu halaman per level indeks (yaitu 5 halaman). Ini disebut "Indeks Pencarian". Jika ada beberapa catatan yang sesuai dengan tagihan saya mungkin harus mengikuti indeks yang diurutkan untuk sementara waktu untuk mengambil semuanya. Tetapi mari kita asumsikan hanya ada satu catatan.

Jadi, tanpa menjalankan indeks permintaan itu diperlukan 1.000.000 dibaca, dengan indes itu diperlukan 5 membaca. Meskipun pembacaan logis adalah operasi di-memori masih ada biaya besar - pada kenyataannya itu adalah operasi paling mahal dalam permintaan sepele seperti yang di atas. Jadi mengurangi jumlah pembacaan logis yang dibutuhkan oleh faktor 200.000 akan mempercepat permintaan Anda dengan faktor yang sama.

Jadi, pembacaan logis tidak sama dengan pemindaian tabel, tetapi pemindaian tabel menyebabkan pembacaan yang jauh lebih logis daripada pencarian indeks.

Sebastian Meine
sumber
> "... mengurangi jumlah mereka (misalnya dengan menambahkan indeks yang sesuai) dapat membuat kueri Anda berjalan lebih cepat." Bisakah Anda menjelaskan bagaimana menambahkan indeks akan mengurangi (?) Pembacaan logis? Apakah logis dibaca identik dengan pemindaian tabel?
1
Menambahkan penjelasan pada jawaban saya di atas.
Sebastian Meine
Terima kasih. Bahkan dengan asumsi indeks yang tepat ada di semua tabel yang terlibat ... Saya pikir masih ada perbedaan kinerja yang sangat besar antara tabel yang disematkan dalam memori vs dibaca dari disk (asumsikan indeks yang sama di kedua skenario) ... atau di lainnya kata-kata, menambahkan indeks akan membuat Anda sedikit meningkatkan kinerja pada mesin dengan banyak RAM daripada pada mesin dengan memori kurang .... benar?
1
akses disk fisik jelas urutan besarnya lebih mahal daripada akses memori. Jadi mengambil tindakan untuk menghindarinya akan membuat Anda jauh. Anda masih harus melihat jumlah pembacaan logis terlebih dahulu saat penyetelan kueri. Menjaga mereka tetap rendah pada gilirannya akan membuat pembacaan fisik rendah. Ada juga kemungkinan besar bahwa halaman tidak harus diusir dari cache mengurangi bahkan membaca fisik yang diperlukan.
Sebastian Meine
2
Nitpick kecil - Saya pikir halamannya 8kb :-). Jawaban yang bagus.
onupdatecascade
3
  • apakah ada cara untuk mengaktifkan penelusuran untuk memantau prosedur tersimpan yang bersarang untuk menemukan bagian yang sangat mahal?

Anda dapat menggunakan SQL Profiler. Ketika Anda memulai penelusuran, Anda harus memilih RPC Completed, SP Starting, SP StmtStarting dan SP StmtCompleted (lihat gambar di bawah)

masukkan deskripsi gambar di sini

Ini akan memungkinkan Anda melihat setiap permintaan yang berjalan di dalam prosedur tersimpan. Ini akan membiarkan Anda melihat berapa kali prosedur tersimpan bersarang dipanggil. Ketika jejak sudah selesai, Anda harus menyimpannya. Kemudian, buka kembali, dan setelah itu, Anda akan dapat memfilter (dengan tombol "Filter kolom") untuk menemukan pertanyaan yang menyebabkan masalah. (mis: kueri yang membutuhkan lebih dari x membaca atau yang bertahan lebih dari x detik (durasi) ...)

Opsi profiler yang saya tunjukkan juga menunjukkan rencana eksekusi, yang juga banyak membantu.

Danielle Paquette-Harvey
sumber
1

Sepertinya pertanyaan optimasi permintaan umum. Dari uraian Anda, saya akan:

  1. Lihatlah kode untuk melihat apakah itu memproses baris-demi-baris. Jika ya, maka sering kali pesanan peningkatan besar dapat dilakukan dengan menerapkan logika yang sama menggunakan set (beberapa baris diproses pada waktu yang sama). Dengan kata lain, jika itu bertindak seperti "lingkaran di atas setiap baris" ubahlah menjadi "proseskan semua baris." SQL unggul karena pengoptimal dapat memilih dari metode yang lebih mungkin, berpotensi menggunakan paralelisme, menghapus banyak overhead yang berasal dari satu baris pada satu waktu.
  2. Pastikan, selanjutnya, bahwa ada indeks yang mendukung pekerjaan. Seringkali, sekali lagi, pesanan peningkatan besar dapat dimiliki dengan indeks yang benar vs tidak. Ini berlaku di memori dan dengan akses disk. Proses masih bisa memakan waktu berjam-jam dengan semua yang ada di RAM jika tidak ada indeks yang sesuai pada set data besar.
  3. Selanjutnya, dengan mengatur logika dan indeks di tempat, saya akan melihat apakah halaman data yang terpengaruh sesuai dengan memori. Pada titik ini, jika masih ada banyak akses disk, melihat pembacaan fisik dan aktivitas disk masuk akal, karena semua keuntungan besar dari pengoptimalan dilakukan dalam dua langkah pertama.
onupdatecascade
sumber