Sdílet prostřednictvím


Problémy s výkonem T-SQL

platí pro:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceSQL databáze v Microsoft Fabric

Při analýze kódu T-SQL v databázovém projektu může být jedno nebo více upozornění zařazeno do kategorií jako problémy s výkonem. Měli byste vyřešit problém s výkonem, abyste se vyhnuli následující situaci:

  • Při spuštění kódu dojde ke kontrole tabulky.

Obecně můžete potlačit problém s výkonem, pokud tabulka obsahuje tak málo dat, že kontrola nezpůsobí výrazný pokles výkonu.

Poskytnutá pravidla identifikují následující problémy s výkonem:

SR0004: Vyhněte se použití sloupců, které nemají indexy jako testovací výrazy v predikátech IN

Prohledávání tabulky způsobíte, když použijete klauzuli WHERE, která odkazuje na jeden nebo více sloupců, které nejsou indexovány jako součást predikátu IN. Prohledávání tabulky snižuje výkon.

Jak opravit porušení

Pokud chcete tento problém vyřešit, musíte provést jednu z následujících změn:

  • Změňte predikát IN tak, aby odkazovaly pouze na sloupce, které mají index.
  • Přidejte index do libovolného sloupce, na který predikát IN odkazuje a který ještě nemá index.

Example

V tomto příkladu jednoduchý příkaz SELECT odkazuje na sloupec [c1], který neměl index. Druhý příkaz definuje index, který můžete přidat k vyřešení tohoto upozornění.

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: Vyhněte se používání vzorů, které začínají na "%" v predikátech LIKE

Kontrolu tabulky můžete způsobit, pokud použijete klauzuli WHERE, která obsahuje predikát LIKE, například řetězec%pattern, k vyhledání textu, který může nastat kdekoli ve sloupci.

Jak opravit porušení

Pokud chcete tento problém vyřešit, měli byste vyhledávací řetězec změnit tak, aby začíná znakem, který není zástupným znakem (%), nebo byste měli vytvořit fulltextový index.

Example

V prvním příkladu příkaz SELECT způsobí prohledávání tabulky, protože hledaný řetězec začíná zástupným znakem. V druhém příkladu příkaz způsobí hledání indexu, protože hledaný řetězec nezačíná zástupným znakem. Hledání indexu načte pouze řádky, které odpovídají klauzuli 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: Přesunutí odkazu na sloupec na jednu stranu relačního operátoru pro použití indexu sloupce

Kód může způsobit prohledávání tabulky, pokud porovná výraz, který obsahuje odkaz na sloupec.

Jak opravit porušení

Chcete-li tento problém vyřešit, musíte přepracovat porovnání tak, aby odkaz na sloupec byl zobrazen samostatně na jedné straně relačního operátoru místo uvnitř výrazu. Když spustíte kód, který obsahuje odkaz na sloupec sám na jedné straně relačního operátoru, SQL Server může použít index sloupce a neprovádí se kontrola tabulky.

Example

V prvním postupu klauzule WHERE obsahuje sloupec [c1] ve výrazu jako součást porovnání. Ve druhém postupu jsou výsledky porovnání identické, ale nikdy nevyžadují prohledávání tabulky.

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: Ve výrazech použijte ISNULL(column, default_value) u sloupců, které mohou mít hodnotu null.

Pokud váš kód porovná dvě NULL hodnoty nebo hodnotu s jinou NULL hodnotou, vrátí váš kód neznámý výsledek.

Jak opravit porušení

Měli byste explicitně určit, jak zpracovávat NULL hodnoty ve výrazech porovnání tak, že zabalíte každý sloupec, který může obsahovat NULL hodnotu ve ISNULL funkci.

Example

Tento příklad ukazuje jednoduchou definici tabulky a dvě uložené procedury. Tabulka obsahuje sloupec, c2který může obsahovat NULL hodnotu. První postup , ProcedureWithWarningporovnává c2 s konstantní hodnotou. Druhý postup problém vyřeší zabalením c2 do volání funkce 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: Extrahování deterministických volání funkcí z predikátů WHERE

V predikátu WHERE je volání funkce deterministické, pokud jeho hodnota nezávisí na vybraných datech. Taková volání by mohla způsobit nepotřebné prohledávání tabulek, což snižuje výkon databáze.

Jak opravit porušení

Pokud chcete tento problém vyřešit, můžete přiřadit výsledek volání proměnné, kterou použijete v predikátu WHERE.

Example

V prvním příkladu uložená procedura obsahuje deterministické volání funkce , ABS(@param1)v predikáte WHERE. V druhém příkladu obsahuje dočasná proměnná výsledek volání.

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