Arquivo
Nova Geração de Notebooks DELL
Quad Core, 16Gb RAM, 1TB RAID, 1Gb de vídeo.
Se alguém quiser fazer uma doação compra esse notebook pra mim por favor.
Ficarei bastante agradecido.
Video:
Site:
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…
10 pontos que devem ser observados quanto a performance de uma consulta Parte 3
Seguindo a série de boas práticas em relação a performance…
4. É muito comum durante o desenvolvimento de um código SQL necessitarmos zerar o valor das variáveis que serão utilizadas no código.
Uma dica em relação a performance é que o comando SELECT é mais rápido do que o SET, porém está regra só se aplica quando podemos substituir um bloco de SET por um SELECT por ex:
|
— Executa um loop zerando o valor de 10 variáveis utilizando SET — Gere o plano de execução e repare que no plano de execução que no Loop o SQL gera um SELECT para cada comando SET. DECLARE @i Int, @Test1 int, @Start datetime DECLARE @V1 Char(6), @V2 Char(6), @V3 Char(6), @V4 Char(6), @V5 Char(6), @V6 Char(6), @V7 Char(6), @V8 Char(6), @V9 Char(6), @V10 Char(6);
SET @Test1 = 0 SET @i = 0 SET @Start = GetDate() WHILE @i < 50000 BEGIN SET @V1 = ” SET @V2 = ” SET @V3 = ” SET @V4 = ” SET @V5 = ” SET @V6 = ” SET @V7 = ” SET @V8 = ” SET @V9 = ” SET @V10 = ” SET @i = @i + 1 END SET @Test1 = DATEDIFF(ms, @Start, GetDate()) SELECT @test1
GO — Executa um loop zerando o valor de 10 variáveis utilizando SELECT — Diferente do primeiro plano de execução o SQL gerou apenas 1 instrução para setar os valores para as 10 variáveis. DECLARE @i Int, @Test1 int, @Start datetime DECLARE @V1 Char(6), @V2 Char(6), @V3 Char(6), @V4 Char(6), @V5 Char(6), @V6 Char(6), @V7 Char(6), @V8 Char(6), @V9 Char(6), @V10 Char(6);
SET @Test1 = 0 SET @i = 0 SET @Start = GetDate() WHILE @i < 50000 BEGIN SELECT @V1 = ”, @V2 = ”, @V3 = ”, @V4 = ”, @V5 = ”, @V6 = ”, @V7 = ”, @V8 = ”, @V9 = ”, @V10 = ”, @i = @i + 1; END SET @Test1 = DATEDIFF(ms, @Start, GetDate()) SELECT @test1 |
5. Pequenas dicas para procedures..
a. Sempre que uma procedure é executada o server envia para o client o número de linhas afetadas pela procedure, normalmente esta informação não é necessária. Desabilitando este comportamento poderemos reduzir o trafego gerado pelo Server e o Client. Portanto sempre que possível inclua o SET NOCOUNT ON no início de suas procedures. Pode ser que isso não gere muita diferença em uma proc que efetua 1 insert mas quando estamos falando de um loop que efetua 1000000 de inserts daí com certeza vai ser um grade ganho de trafego desnecessário que estaria rolando na rede.
b. Só use a opção WITH ENCRYPTION e WITH RECOMPILE caso seja realmente necessário. Lembre-se de que existem programas que conseguem descriptogravar um proc que está criptografada no banco.
c. Não inicie o nome de suas procedure com sp… este prefixo é reservado para procedures do sistema, sempre que você executa uma procedure que inicia com sp… o SQL irá procurar a proc no banco Master e se ela não estiver lá então ele irá resolver o nome da proc no banco atual. Evite este passo adicional simplesmente renomeando as procedures para por exemplo usp ou st.
d. Caso tenha que rodar algum código TSQL no meio da proc evite utilizar o EXEC ao invés disso use a sp_ExecuteSQL pois ao contrário do EXEC a sp_ExecuteSQL irá compilar o SQL para gerar um plano de execução para sua consulta, o quer dizer que caso o plano já tenha sido gerado na próxima execução do código ele irá utilizar o plano que ficou em cachê, evitando a recompilação do código a cada execução.
FIX e Patchs de Correção II
FIX e Patchs de Correção
Pessoal vamos ficar atentos para os Fix de correção de erros do SQL Server, não basta atualizar até o último Service Pack e esperar pelo próximo SP pois tem existem várias correções que são lançadas e que ainda não estão em um Service Pack.
Nos últimos 2 meses tivemos problema 2 problemas em nossos clientes que estavam com uma versão com um problema que já havia sido corrigido.
1º Problema;
O primeiro foi em um cliente que utilizava SQL Server 2000 com Service Pack 3, e tivemos um erro que ao rodar uma consulta com um where IS NULL mesmo assim retornava um valor que não era NULL.
Por ex:
select * from tabela
where Cod IS NULL
O comando acima retornava um Cod que não era null contrariando o filtro do WHERE.
Este problema foi corrigido no SP 4 do SQL 2000, como podemos ver no KB abaixo.
FIX: A parallel query may return unexpected results
http://support.microsoft.com/kb/814509/en-us
Para resolver temporariamente até o cliente atualizar seu servidor utilizamos a clausula OPTION (MAXDOP 1) nos selects.
2º Problema;
Outro erro que pegamos foi no SQL Server 2005 SP2 onde ao rodar uma procedure com um texto muito grande e usando a opção WITH ENCRYPTION o SQL gerava um erro.
Este problema foi corrigido com um FIX que já foi lançado e é bem provável que estará entre os FIX de correção que serão lançados com o SP3 do SQL Server 2005, podemos ver mais detalhes do problema e baixar o FIX no KB abaixo.
FIX: Error message when you run a long stored procedure that is encrypted in SQL Server 2005: "A stack overflow occurred in the server while compiling the query"
http://support.microsoft.com/kb/934246/en-us
Scripts and Tools for Performance Tuning and Troubleshooting SQL Server 2005
E tem gente que ainda pergunta porque eu gosto da Microsoft!
Acesse e pegue uma coleção muito boa de scripts para o SQL Server 2005.
Aproveitando o embalo acesse o Toolbox do CAT para mais arquivos e aplicativos úteis para SQL.
Community Zone 2008
Acabei de receber um convite para participar do Community Zone 2008 que será no Hotel Vila Santo Agostinho em Bragança Paulista.
Show de Bola! Baseado no que vi dos eventos anteriores a este deve ser muito bom. Fora que irei estar no meio dos maiores influenciadores e colaboradores da Microsoft…
Para enviar o convite eles avaliaram a minha contribuição nas comunidades técnicas como:
• Fóruns de discussão (quantidade de respostas com alta qualidade e/ou moderação);
• Artigos técnicos publicados na comunidades MSDN e TechNet;
• WebCasts entregues através do MSDN e TechNet;
• Eventos Presenciais;
• Contribuições com grupo de usuários;
• Participação em Projetos dos Centros de Inovação e/ou Adoption Labs da Microsoft
Já confirmei minha presença, quando eu voltar conto como foi J
Tem lógica ?
Meu Deus, cada uma que aparece, vejam isso.
O mais novo MVP em SQL Server Denis Gobo postou no Blog dele.
SQL Teaser: Where Clause Gone Wild
Try to guess what this WHERE clause is supposed to do.
WHERE
r.ApptId IS NULL
AND r.DATE >= ISNULL(NULL , ‘1/1/1900’)
AND r.DATE < DATEADD(d , 1 , ISNULL(NULL , ‘1/1/3000’))
AND
–Filter on resource
( ( NULL IS NOT NULL
AND r.DoctorResourceID IN ( NULL ) )
OR ( NULL IS NULL ) )
AND –Filter on facility
( ( NULL IS NOT NULL
AND r.FacilityID IN ( NULL ) )
OR ( NULL IS NULL ) )
AND –Filter on Inactive
ISNULL(r.inactive , 0) = 0
ORDER BY
ISNULL(g.LAST , ”) + ISNULL(g.FIRST , ”)
If you think I made that up, then you are in for a surprise. This is actually part of a query, I found it here: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3662895&SiteID=1
This NULL IS NULL and NULL IS NOT NULL stuff is just killing me. I wonder why this person did not get an answer yet…..Enjoy your weekend 🙂
WebCast – XML no SQL Server 2005
Hoje, fiz a WebCast falando de XML no SQL Server 2005,
Idera VS Minha Coffee Mug
Eles são rápidos, o Jorge Aguilar da Idera já me ligou e respondeu o e-mail dizendo que irão me mandar um Package da Idera.
I Love the Power of the Internet.
Ou será que o FBI apertou os caras? Hahahaha.





