Bagikan melalui


Masalah performa T-SQL

Berlaku untuk:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceDatabase SQL di Microsoft Fabric

Saat Anda menganalisis kode T-SQL dalam proyek database Anda, satu atau beberapa peringatan mungkin dikategorikan sebagai masalah performa. Anda harus mengatasi masalah performa untuk menghindari situasi berikut:

  • Pemindaian tabel terjadi saat kode dijalankan.

Secara umum, Anda mungkin menekan masalah performa jika tabel berisi begitu sedikit data sehingga pemindaian tidak akan menyebabkan performa turun secara signifikan.

Aturan yang disediakan mengidentifikasi masalah performa berikut:

SR0004: Hindari menggunakan kolom yang tidak memiliki indeks sebagai ekspresi pengujian dalam predikat IN

Anda akan memicu pemindaian tabel jika Anda menggunakan klausa WHERE yang mengacu pada satu atau beberapa kolom yang tidak diindeks dalam predikat IN. Pemindaian tabel mengurangi performa.

Cara memperbaiki pelanggaran

Untuk mengatasi masalah ini, Anda harus membuat salah satu perubahan berikut:

  • Ubah predikat IN untuk mereferensikan hanya kolom yang memiliki indeks.
  • Tambahkan indeks ke kolom apa pun yang dirujuk predikat IN dan yang belum memiliki indeks.

Example

Dalam contoh ini, pernyataan SELECT sederhana mereferensikan kolom, [c1], yang tidak memiliki indeks. Pernyataan kedua menentukan indeks yang dapat Anda tambahkan untuk mengatasi peringatan ini.

CREATE PROCEDURE [dbo].[Procedure3WithWarnings]
AS
SELECT [Comment]
FROM [dbo].[Table2]
WHERE [c1] IN (1, 2, 3)

CREATE INDEX [IX_Table2_C1]
ON [dbo].[Table2] (c1);

SR0005: Hindari menggunakan pola yang dimulai dengan "%" dalam predikat LIKE

Anda dapat menyebabkan pemindaian tabel jika Anda menggunakan klausa WHERE yang berisi predikat LIKE seperti '%pattern string' untuk mencari teks yang dapat terjadi di mana saja dalam kolom.

Cara memperbaiki pelanggaran

Untuk mengatasi masalah ini, Anda harus mengubah string pencarian sehingga dimulai dengan karakter yang bukan wildcard (%), atau Anda harus membuat indeks teks penuh.

Example

Dalam contoh pertama, pernyataan SELECT menyebabkan pemindaian seluruh tabel karena string pencarian dimulai dengan karakter wildcard. Dalam contoh kedua, pernyataan tersebut menyebabkan pencarian indeks karena string pencarian tidak dimulai dengan karakter wildcard. Pencarian indeks hanya mengambil baris yang cocok dengan klausa WHERE.

SELECT [dbo].[Table2].[ID], [dbo].[Table2].[c1], [dbo].[Table2].[c2], [dbo].[Table2].[c3], [dbo].[Table2].[Comment]
FROM dbo.[Table2]
WHERE Comment LIKE '%pples'

SELECT [dbo].[Table2].[ID], [dbo].[Table2].[c1], [dbo].[Table2].[c2], [dbo].[Table2].[c3], [dbo].[Table2].[Comment]
FROM dbo.[Table2]
WHERE Comment LIKE 'A%'

SR0006: Memindahkan referensi kolom ke satu sisi operator perbandingan untuk menggunakan indeks kolom

Kode Anda dapat menyebabkan pemindaian tabel jika membandingkan ekspresi yang berisi referensi kolom.

Cara memperbaiki pelanggaran

Untuk mengatasi masalah ini, Anda harus mengerjakan ulang perbandingan sehingga referensi kolom muncul sendiri di satu sisi operator perbandingan, bukan di dalam ekspresi. Saat Anda menjalankan kode yang memiliki referensi kolom saja di satu sisi operator perbandingan, SQL Server dapat menggunakan indeks kolom, dan tidak ada pemindaian tabel yang dilakukan.

Example

Dalam prosedur pertama, klausa WHERE menyertakan kolom [c1] dalam ekspresi sebagai bagian dari perbandingan. Dalam prosedur kedua, hasil perbandingan identik tetapi tidak pernah memerlukan pemindaian tabel.

CREATE PROCEDURE [dbo].[Procedure3WithWarnings]
@param1 int
AS
SELECT [c1], [c2], [c3], [Comment]
FROM [dbo].[Table2]
WHERE ([c1] + 5 > @param1)

CREATE PROCEDURE [dbo].[Procedure3Fixed]
@param1 int
AS
SELECT [c1], [c2], [c3], [Comment]
FROM [dbo].[Table2]
WHERE ([c1] > (@param1 - 5))

SR0007: Gunakan ISNULL(column, default_value) pada kolom nullable dalam ekspresi

Jika kode Anda membandingkan dua NULL nilai atau NULL nilai dengan nilai lain, kode Anda mengembalikan hasil yang tidak diketahui.

Cara memperbaiki pelanggaran

Anda harus secara eksplisit menunjukkan cara menangani NULL nilai dalam ekspresi perbandingan dengan membungkus setiap kolom yang dapat berisi NULL nilai dalam ISNULL fungsi.

Example

Contoh ini menunjukkan definisi tabel sederhana dan dua prosedur tersimpan. Tabel berisi kolom, c2, yang dapat berisi NULL nilai. Prosedur pertama, ProcedureWithWarning, dibandingkan dengan nilai konstanta c2 . Prosedur kedua memperbaiki masalah dengan membungkus c2 dengan panggilan fungsi ISNULL.

CREATE TABLE [dbo].[Table1]
(
[ID] INT NOT NULL IDENTITY(0, 1),
[c1] INT NOT NULL PRIMARY KEY,
[c2] INT
)
ON [PRIMARY]

CREATE PROCEDURE [dbo].[ProcedureWithWarning]
AS
BEGIN
SELECT COUNT(*) FROM [dbo].[Table1]
 WHERE [c2] > 2;
END

CREATE PROCEDURE [dbo].[ProcedureFixed]
AS
BEGIN
SELECT COUNT(*) FROM [dbo].[Table1]
WHERE ISNULL([c2],0) > 2;
END

SR0015: Mengekstrak panggilan fungsi deterministik dari predikat WHERE

Dalam predikat WHERE, panggilan fungsi bersifat deterministik jika nilainya tidak bergantung pada data yang dipilih. Panggilan tersebut dapat menyebabkan pemindaian tabel yang tidak perlu, yang mengurangi performa database.

Cara memperbaiki pelanggaran

Untuk mengatasi masalah ini, Anda dapat menetapkan hasil panggilan ke variabel yang Anda gunakan dalam predikat WHERE.

Example

Dalam contoh pertama, prosedur tersimpan mencakup panggilan fungsi deterministik, ABS(@param1), dalam predikat WHERE. Dalam contoh kedua, variabel sementara menyimpan hasil panggilan.

CREATE PROCEDURE [dbo].[Procedure2WithWarning]
@param1 INT = 0,
AS
BEGIN
SELECT [c1], [c2], [c3], [SmallString]
FROM [dbo].[Table1]
WHERE [c2] > ABS(@param1)
END

CREATE PROCEDURE [dbo].[Procedure2Fixed]
@param1 INT = 0,
AS
BEGIN
DECLARE @AbsOfParam1 INT
SET @AbsOfParam1 = ABS(@param1)

SELECT [c1], [c2], [c3], [SmallString]
FROM [dbo].[Table1]
WHERE [c2] > @AbsOfParam1
END