Inicial > SQL Server - Performance > 10 pontos que devem ser observados quanto a performance de uma consulta Parte – 4

10 pontos que devem ser observados quanto a performance de uma consulta Parte – 4

6.       Substituir o uso de CURSOR pelo comando WHILE + tabelas temporárias ou Variáveis do tipo table.

DECLARE @VendorID Int,

        @Name     VarChar(80)

 

DECLARE Cur_Vendor CURSOR FOR

 SELECT VendorID, Name

   FROM Purchasing.Vendor

 

OPEN Cur_Vendor

 

FETCH NEXT FROM Cur_Vendor

 INTO @VendorID, @Name

 

WHILE @@FETCH_STATUS = 0

BEGIN

       PRINT @Name

 

             FETCH NEXT FROM Cur_Vendor

    INTO @VendorID, @Name

END

 

CLOSE Cur_Vendor

DEALLOCATE Cur_Vendor

GO

 

DECLARE @ROWID Int,

        @Name  VarChar(80)

 

SET @ROWID = 0;

 

SELECT TOP 1

       @ROWID = VendorID,

       @Name  = Name     

  FROM Purchasing.Vendor

 WHERE VendorID > @ROWID

 ORDER BY VendorID

 

WHILE @@ROWCOUNT > 0

BEGIN

  PRINT @Name

 

  SELECT TOP 1

         @ROWID = VendorID,

         @Name  = Name     

    FROM Purchasing.Vendor

   WHERE VendorID > @ROWID

   ORDER BY VendorID

END

GO

 

7.       Verificar se as variáveis no WHERE são do mesmo DataType que a coluna da tabela.

DECLARE @TMP TABLE(Nome VarChar(80) PRIMARY KEY)

 

DECLARE @Nome NVarChar(80)

SET @Nome = ‘Teste’

 

— Gera FULL SCAN

SELECT * FROM @TMP

 WHERE Nome = @Nome

 

GO

 

DECLARE @TMP TABLE(Nome VarChar(80) PRIMARY KEY)

 

DECLARE @Nome VarChar(80)

SET @Nome = ‘Teste’

 

— Gera SEEK

SELECT * FROM @TMP

 WHERE Nome = @Nome

 

8.       Verificar se existe uso de variáveis do tipo Table para grande volume de dados, pois isso pode causar problema de performance já que variáveis do tipo table não usam proveito de paralelismo e não criam estatísticas com os dados da tabela.

9.       Verificar se é possível usar o conceito de Hash Index usando o CheckSum para gerar o número HASH, Caso existam colunas com valores muito grandes as vezes compensa usar o CheckSum para gerar o Hash e depois indexar a coluna hash.

— Create a checksum index.

SET ARITHABORT ON;

USE AdventureWorks;

GO

ALTER TABLE Production.Product

ADD cs_Pname AS CHECKSUM(Name);

GO

CREATE INDEX Pname_index ON Production.Product (cs_Pname);

GO

/*Use the index in a SELECT query. Add a second search

condition to catch stray cases where checksums match,

but the values are not the same.*/

SELECT *

FROM Production.Product

WHERE CHECKSUM(N’Bearing Ball’) = cs_Pname

AND Name = N’Bearing Ball’;

GO

10.       Evite usar a clausula IN.

IF OBJECT_ID(‘tempdb.dbo.#TMP’) IS NOT NULL

BEGIN

  DROP TABLE #TMP

END

 

CREATE TABLE #TMP (ID Int IDENTITY(1,1) PRIMARY KEY)

GO

 

INSERT INTO #TMP DEFAULT VALUES

INSERT INTO #TMP DEFAULT VALUES

INSERT INTO #TMP DEFAULT VALUES

INSERT INTO #TMP DEFAULT VALUES

INSERT INTO #TMP DEFAULT VALUES

GO

 

SET STATISTICS PROFILE ON

SET STATISTICS IO ON

 

SELECT * FROM #TMP

 WHERE ID IN (1,2,3,4,5)

 

 

/*

Coluna argument

 

OBJECT:([tempdb].[dbo].[#TMP]),

       SEEK:(

               [tempdb].[dbo].[#TMP].[ID]=(1) OR

               [tempdb].[dbo].[#TMP].[ID]=(2) OR

               [tempdb].[dbo].[#TMP].[ID]=(3) OR

               [tempdb].[dbo].[#TMP].[ID]=(4) OR

               [tempdb].[dbo].[#TMP].[ID]=(5)

            )

       ORDERED FORWARD

 

Repare no argument que o SQL gerou, ou seja irá acessar uma vez a tabela #TMP para cada opção do IN

podemos confirmar isso no Scan Count do statistics io

 

— IO

Scan count 5, logical reads 10, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 

*/

GO

 

SELECT * FROM #TMP

 WHERE ID BETWEEN 1 AND 5

/*

OBJECT:([tempdb].[dbo].[#TMP]),

       SEEK:(

              [tempdb].[dbo].[#TMP].[ID] >= (1) AND

              [tempdb].[dbo].[#TMP].[ID] <= (5)

            )

       ORDERED FORWARD

 

Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 

Repare na diferença de IO.

*/

 

Espero que tenham gostado, eu adorei J, gostei tanto que vou começar a escrever uma série de artigos sobre o Query Optimizer, fiquem de olho…

  1. Danilo
    27 de maio de 2009 às 12:10

    Oi FabioEstou usando variaveis de tipo tabela para grandes volumes de dados em algumas funcoes. Sabendo que funcoes nao permitem o uso de tabelas temporarias o que segures que eu use?Obrigado antecipandamente

  2. Fabiano Neves
    2 de junho de 2009 às 16:52

    Olá Danilo, Neste caso o ideal seria você pensar me criar uma Proc, e utilizar tabelas temporárias e indexar estas tabelas, não acha?Abraço.

  3. Thiago Alencar
    3 de dezembro de 2010 às 13:46

    Muito bom a seria de materias de performance. Tão bom que, merece mais artigos..
    Parabens
    Absssss

  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: