Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

SQL Server Internal:Operator Bermasalah Pt. Saya – Memindai

SQL Server telah ada selama lebih dari 30 tahun, dan saya telah bekerja dengan SQL Server hampir selama itu. Kalen mencakup pemindaian di Bagian Pertama SQL Server Internal:Operator Bermasalah.

Saya telah melihat banyak perubahan selama bertahun-tahun (dan beberapa dekade!) Dan versi produk luar biasa ini. Dalam posting ini saya akan berbagi dengan Anda bagaimana saya melihat beberapa fitur atau aspek SQL Server, terkadang bersama dengan sedikit perspektif historis.

Menyetel kueri SQL Server Anda adalah salah satu hal terbaik yang dapat Anda lakukan untuk kinerja yang lebih baik dan optimalisasi diagnostik server SQL. Tapi penyetelan adalah topik besar! Mengetahui dengan tepat cara menyetel dengan cara terbaik tidak hanya membutuhkan pengetahuan menyeluruh tentang data dan beban kerja Anda, tetapi juga pengetahuan tentang bagaimana SQL Server benar-benar membuat pilihan eksekusi rencananya. Jadi, apa yang dapat Anda lakukan jika Anda bukan ahli dalam SQL Server Internals? Satu hal yang dapat Anda lakukan adalah mengandalkan orang-orang yang ahli, serta alat yang ditulis oleh para ahli. Alat seperti Quest Spotlight Cloud Tuning Pack dapat memberi Anda beberapa saran bagus untuk memulai perjalanan menuju kinerja kueri yang lebih baik. Tentu saja, tidak ada alat eksternal yang mengetahui data Anda dan semua detail dari semua beban kerja Anda, jadi pengujian menyeluruh atas saran apa pun yang Anda putuskan untuk diterapkan selalu disarankan.

Dalam posting ini tentang operator yang bermasalah, saya akan menganggap Anda memiliki pengetahuan dasar tentang struktur indeks SQL Server. Berikut adalah beberapa informasi yang akan membantu:

  • Tabel tanpa indeks berkerumun disebut heap dan tidak memiliki pengurutan. Tidak ada baris pertama atau baris terakhir. Heap hanyalah sekumpulan baris tanpa urutan tertentu.
  • Level daun dari indeks berkerumun adalah tabel itu sendiri. (Ini bukan salinan tabel, ini ADALAH tabel.) Baris indeks secara logis diurutkan oleh kolom apa pun yang didefinisikan sebagai kunci indeks berkerumun.
  • Level level dari indeks nonclustered berisi baris indeks untuk setiap baris dalam tabel. Baris berisi kolom kunci nonclustered dan diurutkan secara logis dalam urutan kunci yang ditentukan. Selain kolom kunci, baris indeks nonclustered berisi 'bookmark' yang menunjuk ke baris yang direferensikan dalam tabel. Bookmark dapat dalam salah satu dari dua bentuk:
    1. Jika tabel memiliki indeks berkerumun, bookmark adalah kunci indeks berkerumun. (Jika kunci indeks yang dikelompokkan adalah bagian dari kunci indeks yang tidak dikelompokkan, itu tidak akan diduplikasi.)
    2. Jika tabel adalah heap, bookmark adalah ID Baris, atau RID, yang menentukan lokasi fisik baris. Lokasi biasanya ditentukan sebagai FileNum:PageNum:RowNum .

Alat SQL Server sendiri menyediakan banyak cara untuk melihat rencana eksekusi kueri yang diputuskan oleh pengoptimal untuk digunakan untuk kueri tertentu. Dengan tambahan Quest Spotlight Tuning Pack, Anda bisa mendapatkan lebih banyak informasi tentang paket Anda.

Kode berikut membuat salinan dua tabel di AdventureWorks database (saya menggunakan AdventureWorks2016 , tetapi Anda dapat menggunakan versi lain).

USE AdventureWorks2016;

GO

DROP TABLE IF EXISTS SalesHeader;

GO

SELECT *

INTO SalesHeader

FROM Sales.SalesOrderHeader;

GO

DROP TABLE IF EXISTS SalesDetail;

GO

SELECT * INTO SalesDetail

FROM Sales.SalesOrderDetail;

GO

Sekarang jalankan kueri yang menggabungkan dua tabel, setelah mengaktifkan “Sertakan Rencana Eksekusi Aktual”

SELECT h.SalesOrderID, OrderDate, ProductID, UnitPrice, OrderQty

FROM SalesHeader h JOIN SalesDetail d

ON h.SalesOrderID = d.SalesOrderID

WHERE SalesOrderDetailID < 100;

GO

Paket Penyetelan Spotlight Quest akan melaporkan masalah dengan kueri, jadi Anda dapat mengklik "Lihat Analisis" dan pilih opsi "Rencana Eksekusi". Anda akan melihat yang berikut ini:

Memahami Pemindaian Tabel

Pertama, saya ingin mengambil risiko dan mengatakan tidak ada operator paket yang selalu buruk! Mengapa pengoptimal menambahkannya ke rencana kueri Anda jika itu buruk? Ini mungkin menunjukkan ada ruang untuk perbaikan dalam data atau struktur indeks Anda, tetapi itu sendiri tidak buruk.

Dalam contoh di atas, Paket Tuning tampaknya menyoroti pemindaian tabel, yang menunjukkan bahwa mereka mungkin bermasalah. Tetapi tidak selalu benar bahwa pemindaian tabel bermasalah. Situasi yang jauh lebih buruk adalah menggunakan pencarian indeks nonclustered untuk kueri yang mengakses setiap baris dalam tabel. Untuk kueri khusus ini, saya setuju bahwa pemindaian mungkin bukan hal yang baik karena kami hanya tertarik pada beberapa baris di SalesDetail tabel (99 dari 121.317 baris, atau kurang dari sepersepuluh persen.)

Jadi, kita bisa melihat saran di panel Analisis untuk membangun indeks. Saran untuk Detail Penjualan tabel adalah untuk membangun indeks nonclustered pada SalesOrderID kolom (kolom dalam klausa JOIN) dan INCLUDE setiap kolom lain dalam tabel yang dikembalikan oleh kueri. Saran untuk SalesHeader tabel adalah indeks nonclustered pada SalesOrderDetailId kolom, yang merupakan kolom dalam klausa WHERE, dan TERMASUK OrderDate kolom, yang merupakan satu-satunya kolom lain yang dikembalikan dari tabel ini.

Bagaimana jika kueri kita sedikit berbeda? Bagaimana jika saya menjalankan kueri ini menggunakan SELECT * alih-alih daftar kolom tertentu. Jika Anda mencobanya, dan melihat rekomendasi, disarankan menggunakan INCLUDE untuk setiap kolom dalam tabel selain kolom kunci tunggal. Meskipun indeks semacam itu mungkin membuat kueri khusus ini berjalan sedikit lebih cepat, itu bisa memperlambat kueri lain, khususnya kueri UPDATE Anda. Indeks ini pada dasarnya hanyalah salinan tabel, karena tingkat daun indeks akan berisi setiap kolom dalam tabel. Jika Anda melihat rekomendasi seperti ini, menyarankan indeks yang menyertakan semua kolom dalam tabel, saya sangat menyarankan untuk mundur sedikit dan tidak membuatnya secara membabi buta.

Penyetelan kueri untuk diagnostik server SQL Anda tidak hanya melibatkan pengelolaan indeks, tetapi juga pengelolaan kueri itu sendiri. Untuk kueri khusus ini, kita mungkin sebenarnya lebih baik menulis ulang kueri untuk TIDAK menggunakan SELECT * untuk mengembalikan setiap baris dalam tabel. Mengembalikan hanya sebagian kecil kolom mungkin sudah cukup, dan indeks yang jauh lebih sempit sudah cukup, seperti pada contoh pertama.

Akankah salah satu dari indeks ini benar-benar menjadi indeks yang baik untuk dibuat? Indeks yang lebih sempit akan lebih kecil secara keseluruhan dan tidak akan terlalu terpengaruh oleh pembaruan data. Indeks pada semua kolom seperti salinan kedua dari tabel, diurutkan dalam urutan yang berbeda dari tabel itu sendiri. Ada situasi di mana memiliki 'salinan kedua' dari tabel dalam urutan yang berbeda dapat berguna, tetapi akan ada banyak overhead untuk operasi modifikasi data. Satu-satunya cara untuk mengetahui dengan pasti adalah dengan mencoba rekomendasi pada sistem pengujian dengan beban kerja yang representatif. Hanya Anda yang tahu data dan kueri Anda, jadi cobalah dan lihat!

Memahami Pemindaian Indeks

Seperti yang saya sebutkan di atas, pemindaian tabel tidak selalu merupakan hal yang buruk. Tapi bagaimana dengan indeks scan? Karena tingkat daun indeks berkerumun adalah tabel itu sendiri, pemindaian indeks berkerumun sama dengan pemindaian tabel! jika pemindaian tabel buruk, pemindaian indeks berkerumun juga sama buruknya. Tapi itu tidak selalu buruk. Sekali lagi, Anda perlu mengujinya di sistem Anda.

Rekomendasi dari SQL Server Engine yang Quest Spotlight Tuning Pack tunjukkan bahwa Anda tidak pernah menyarankan indeks berkerumun. itu mungkin menyarankan nonclustered yang mencakup setiap kolom dalam tabel (seperti yang disebutkan sebelumnya), yang hanya merupakan duplikat dari tabel. Mencari tahu kolom atau kolom terbaik untuk indeks berkerumun Anda adalah topik besar itu sendiri, jadi saya tidak akan membahasnya di sini.

Apa itu pencarian? Operasi pencarian dalam rencana berarti SQL Server menggunakan data yang dipesan di pohon indeks untuk menemukan baris, serangkaian baris, atau titik awal dan/atau titik berhenti dalam rentang baris. Secara umum, menggunakan pencarian indeks nonclustered adalah operasi yang sangat masuk akal jika Anda mengembalikan persentase baris yang sangat kecil dari tabel. Tetapi pencarian bukanlah pilihan yang baik untuk kueri yang mengembalikan BANYAK baris dari sebuah tabel. Berapa BANYAK? Tidak ada jawaban sederhana tetapi jika kueri Anda mengembalikan lebih dari beberapa persen baris, Anda harus memastikan bahwa Anda menguji saran indeks secara menyeluruh. Terkadang pemindaian tabel, atau pemindaian indeks berkerumun, lebih baik daripada pencarian indeks. (Untuk salah satu contohnya, lihat posting blog saya di sini).

Alat seperti Paket Penyetelan Spotlight Quest dapat memberi Anda saran bagus untuk memulai perjalanan penyetelan Anda dengan diagnostik server SQL, tetapi semakin Anda tahu tentang cara kerja indeks SQL Server dan pengoptimal SQL Server, semakin baik Anda dapat mengevaluasi saran tersebut untuk kueri dan data, dan bahkan mungkin memberikan saran Anda sendiri.

Dalam posting berikut dalam seri ini, saya akan memberi tahu Anda tentang operator bermasalah lainnya yang mungkin muncul dalam rencana kueri Anda, jadi segera periksa kembali!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Letakkan semua tabel, prosedur tersimpan, pemicu, batasan, dan semua dependensi dalam satu pernyataan sql

  2. Penggunaan SqlParameter dalam klausa SEPERTI SQL tidak berfungsi

  3. Perbedaan antara JOIN dan INNER JOIN

  4. Menghapus nol di depan dari bidang dalam pernyataan SQL

  5. Cara Menginstal SQL Server