Arquivo

Arquivo do Autor

SQL Server em Português

6 de maio de 2010 1 comentário

 

SQL Server em português só podia dar nisso…

image001

Categorias:Não categorizado

Cuidado com Views…

29 de abril de 2010 Deixe um comentário

 

Pessoal já faz um tempo que estou sem blogar né?… Bom mesmo sem escrever para o blog por um tempo, isso não significa que fiquei sem escrever sobre SQL… na verdade bastante coisa aconteceu desde meu último post. Vamos as novidades:

· Tenho escrito bastante para o Simple Talk, a cada semana escrevo sobre um operador dos planos de execução, se você ainda não viu, segue o link para os artigos http://www.simple-talk.com/author/fabiano-amorim/… Ainda tem muito pela frente e eu estou adorando J, espero que eu consiga manter a meta de 1 por semana.

· O tão falado Marília Tech Day foi realmente um sucesso, foi uma honra pra mim poder participar e logo estarei no Prudente TechDay…

Tenho as gravações de minhas palestras e a palestra do Fabricio Catae. Eu fiz duas sessões uma sobre Joins no SQL Server e outra sobre índexação. Acabei sendo pego de surpresa pois o nosso amigo Rodrigo Fernandes teve um imprevisto e não conseguiu pegar o Vôo para o evento, então aproveitei o horário dele e falei sobre Índices no SQL Server, eu achei que ficou legal com bastante exemplos e boas perguntas da galera.

Ainda estou brigando para achar um programa decente para edição dos vídeos, assim que eu conseguir vou subir pro YouTube e coloco os links aqui no blog.

· Eu já havia sido convidado para falar sobre SQL Server em uma faculdade daqui de Tupã, então logo após o Marília TechDay falei sobre Certificações e SQL Server 2008 aqui na FACAT. Foi bem legal, é sempre bom ver a galera entusiasmada com as funcionalidades do SQL J.

Bom acabando a conversa fiada, vamos para o que interessa mais SQL Server.

Eu sempre me surpreendo com as situações que encontro no dia a dia… Hoje eu estava trabalhando em uma procedure que lia alguns dados a partir de uma view, e a consulta não utilizava um determinado índice de jeito nenhum. Fui olhar com calma e encontrei o seguinte cenário.

Vamos criar umas tabelas de teste para entender o problema.

IF OBJECT_ID(‘Pedidos’) IS NOT NULL

BEGIN

DROP TABLE Clientes

DROP TABLE Pedidos

END

GO

CREATE TABLE Pedidos(ID_Pedido   Integer Identity(1,1),

                     ID_Cliente  Int,

                     Data_Pedido DateTime,

                     Valor       Numeric(18,2),

CONSTRAINT xpk_Pedidos PRIMARY KEY (ID_Pedido))

GO

CREATE TABLE Clientes(ID_Cliente    Integer Identity(1,1),

                      Nome_Cliente  VarChar(300)

CONSTRAINT xpk_Clientes PRIMARY KEY (ID_Cliente))

GO

CREATE INDEX ix_teste ON Clientes(Nome_Cliente)

GO

DECLARE @i Integer

SET @i = 0

WHILE @i < 10000

BEGIN

INSERT INTO Pedidos(ID_Cliente,

Data_Pedido,

                      Valor)

VALUES(ABS(CheckSum(NEWID()) / 10000000),

GetDate() – ABS(CheckSum(NEWID()) / 10000000),

ABS(CheckSum(NEWID()) / 1000000))

INSERT INTO Clientes(Nome_Cliente)

VALUES (NEWID())

SET @i = @i + 1

END

GO

SELECT * FROM Pedidos

SELECT * FROM Clientes

Segue um exemplo dos dados incluidos

clip_image002

Tenho uma tabela simples de pedidos e os dados de clientes, agora vou criar uma view que me retorna os dados dos pedidos com o nome do cliente.

CREATE VIEW vw_Teste

AS SELECT Pedidos.*, ISNULL(Clientes.Nome_Cliente,’Não Existe’) AS Nome_Cliente

FROM Pedidos

LEFT OUTER JOIN Clientes

ON Clientes.ID_Cliente = Pedidos.ID_Cliente

Sim, eu fiz o LEFT OUTER JOIN de propósito pois pode acontecer de um registro da Pedidos.ID_Cliente não estar na tabela de Clientes. Estou apenas usando um cenário para exemplo.

Existe um índice por Clientes.Nome_Cliente, vamos ver ele na prática. A consulta abaixo utiliza o mesmo select da view porém desta vez estamos fazendo um filtro por nome_cliente.

SELECT Pedidos.*, ISNULL(Clientes.Nome_Cliente,’Não Existe’) AS Nome_Cliente

FROM Pedidos

LEFT OUTER JOIN Clientes

ON Clientes.ID_Cliente = Pedidos.ID_Cliente   

WHERE Clientes.Nome_Cliente like ‘A%’

clip_image004

Como podemos ver, o plano acima utilizou o índice ix_teste para filtrar os dados

Porem se efetuarmos o mesmo select utilizando a view temos o seguinte plano.

SELECT * FROM vw_Teste

WHERE Nome_Cliente like ‘A%’

clip_image006

Bem, a esta altura você já deve ter identificado qual é o problema. Mas pra quem ainda não pegou, fica a pergunta, porque o SQL faz o seek quando uso o código da view mas quando uso a view ele não faz o seek?

O que acontece é que na view estamos alterando o valor da coluna Nome_Cliente, repare que estou utilizando a function ISNULL para validar se os dados foram retornados, e isso impede que o SQL utilize o índice.

Para resolver este problema, poderiamos retornar duas colunas na view uma com o ISNULL e outra sem o ISNULL efetuar nenhuma alteração nela. Outra forma seria incluir outra coluna que faz parte da tabela Clientes no resultado da view e utilizar esta coluna.

Bom fica a dica.

Abraços

Categorias:Não categorizado

Novo artigo Simple Talk

18 de março de 2010 Deixe um comentário

Galera, saiu outro artigo que escrito pro ST,

Acessem lá…

http://www.simple-talk.com/sql/sql-tools/sql-server-intellisense-vs.-red-gate-sql-prompt/

Valeu

Categorias:Não categorizado

Fabiano vs DeadLock Paralelism

8 de fevereiro de 2010 4 comentários

Galera, espero que este post sirva como ajuda para quem vai para o google a procura de uma resposta…

Pergunta, pode ocorrer um erro de deadlock em um select ?

Resposta: Sim. Um deadklock ocorre quando uma sessão esta esperando para acessar um determinado recurso que esta sendo utilizado por outra sessão. Estes recursos podem ser locks, paralelismo, sessões em espera, ou uma combinação destes itens.

Meu problema foi justamente este de paralelismo, eu tenho uma consulta que estava utilizando paralelismo e as vezes ela apresentava o seguinte erro:

Transaction (Process ID 55) was deadlocked on thread | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Repare no item em negrito e veja que o recurso que esta sendo acessado é esse tal de “communication buffer” que é o que? Paralelismo.

Resumo da ópera, como não sou DBA do ambiente e não posso mexer e nem ver a cor do servidor onde o SQL está instalado, tive que apelar para um OPTION(MAXPDOP 1) na minha proc. Desta forma evito o paralelismo e por consequencia o deadlock.

Abraços

Categorias:Não categorizado

sys.fn_PhysLocFormatter(%%physloc%%)

3 de fevereiro de 2010 Deixe um comentário

Sensacional a dica do Paul Randal sobre uma nova function não documentada… quem já usou o DBCC Page para ver os dados gravados nas páginas sabe do que estou falando.

http://www.sqlskills.com/BLOGS/PAUL/post/SQL-Server-2008-New-%28undocumented%29-physical-row-locator-function.aspx

Pena que só funciona pro SQL2008.

Abraço

Categorias:Não categorizado

TOP 100

1 de fevereiro de 2010 1 comentário

Aqui estou, de volta a rotina, no ônibus a caminho de São Paulo… tempo para ler e escrever um pouco. Por falar em ler vou aproveitar para deixar uma dica ai pra vocês, caso gostem de leitura não deixem de aproveitar a oportunidade de comprar os livros da Série Deixados para Trás no Submarino, a série toda (13 livros) esta em promoção, não, não ganho nada com do Submarino, mas quem gosta de leitura tem que aproveitar… os livros são muito bons, eu li até o oitavo, agora comprei a série toda vou começar a ler tudo denovo… vale muito a pena.

Anyway, vamos logo ao assunto que interessa pra vocês SQL Server.

Entendendo o Problema

Quero compartilhar com vocês um problema bem interessante em uma consulta utilizando TOP e ORDER BY para tabelas com muitos registros.

O problema é o seguinte:  Tenho uma consulta que faz um TOP em uma tabela utilizando a clausula ORDER BY por uma coluna diferente da chave cluster. Quando uso TOP 100 o SQL utiliza 550mb de memória, 9875 de CPU e retorna a consulta em 40 segundos, quando uso TOP 101 o SQL utiliza 798mb de memória, 42745 de CPU e retorna a consulta em 1 minuto e 20 segundos.

A pergunta que não quer calar, porque a inclusão de apenas 1 registro degrada tanto o desempenho?

TOP <= 100 VS TOP > 100

Bom, vamos entender como eu cheguei à conclusão abaixo.

O Operador TOP aplica um SORT para limitar a quantidade de linhas de duas formas, uma utilizando um algoritmo otimizado para ordenar poucas linhas, e outro para ordenar muitas linhas que é o operador de sort normal que conhecemos.

Suponha uma consulta SELECT TOP <N> * FROM TABELA, caso o <N> for >= 100 então o QO utiliza o algoritmo otimizado se o TOP N for > que 100 então ele utiliza o SORT no tempdb. Li esta explicação neste link no connect.

Configuração Ambiente

Entendendo isso, fui realizar os testes para medir a performance, para fazer isso medi o uso CPU, Memória  e Tempo execução das consultas. Utilizei o Profiler para ler o uso de CPU e o Perfom para ler o contador “Total Server Memory”. A cada execução das consultas eu parava e iniciava o banco de dados para obter os valores de uso de memória.

Estou utilizando o SQL Server 2008 versão developer com Service Pack 1, e ele esta configurado para utilizar até 2 gb de memória. Segue a tela de configuração:

clip_image002

Como vocês podem observar nos prints abaixo, criei duas consultas. Ambas fazendo um select com TOP em uma tabela do meu banco de dados, a diferença entre as consultas é justamente o TOP 100 para o TOP 101.

Veja que para o primeiro plano de execução(TOP 100) o SQL Server reservou 1024 kb de memória, e para no segundo plano(TOP 101) ele reservou 224920 kbs de memória.

clip_image004

clip_image006

Veja o gráfico de memória utilizada pelo SQL Server ao rodar a primeira consulta. Repare que o SQL utilizou 553mb de memória e rodou a consulta em 44 segundos(veja no SSMS atrás do PerfMon).

clip_image008

clip_image010

 Agora veja a diferença para a segunda consulta com o TOP 101. Bem diferente não?

clip_image012

clip_image014

Bom galera fica ai a dica… Vale a pena ficar de olho nos TOPs que retornem mais de 100 registros…

Ok ok, eu sei que faltou um item aqui de Conclusão, masss estou cansado, vou tentar dormir um pouco, depois quem sabe não escrevo mais sobre isso?…

Abraços

Categorias:Não categorizado

Datas, Backups

27 de janeiro de 2010 1 comentário

Pessoal, post rápido…

Ontem tivemos um problema no banco de dados que estamos utilizando em ambiente de desenvolvimento. A empresa que fez e nos disponibilizou o backup do baco de dados, jurava que o backup havia sido feito no dia 09/01/2010 as 3 horas da manhã.

Bom para verificar quando o backup havia sido finalizado foi fácil, bastou acessar o servidor e verificar a coluna backup_finish_date da msdb.dbo.backupset. Lá identifiquei que o backup havia terminado as 00:24 e não as 03 como estavam falando.

Fica ai a dica, caso um dia precisem analisar quando um backup foi feito, existem algumas tabelas no banco msdb que gravam varias informações sobre os backups.

Abraço

Categorias:Não categorizado

Novo artigo

7 de janeiro de 2010 Deixe um comentário

Pessoal

Estou MUITO feliz em dizer que outro artigo meu foi publicado no Simple-Talk,

Convido a todos para ler e deixar comentários… (como sempre né galera… positivos…rs.. se tiver alguma coisa errada me manda no e-mail :-))

Particularmente eu acho esse o mais interessante de tudo que já escrevi… bom fica ai pra vcs… abraços

http://www.simple-talk.com/sql/t-sql-programming/13-things-you-should-know-about-statistics-and-the-query-optimizer/

Aaaa, se quiserem ver os outros clique aqui… http://www.simple-talk.com/author/fabiano-amorim/

Categorias:Não categorizado

Como remover um Plano de execução do CachePlan

5 de janeiro de 2010 7 comentários

Pessoal depois de alguns bons dias de férias, volto com uma dica bem legal que li.

Para limpar o PlanCache de uma instância SQL utilizamos o DBCC FREEPROCCACHE, para limpar o cache de apenas um banco específico utilizamos o DBCC FLUSHPROCINDB (<DBID_DO_BANCO>). Mas fica uma pergunta, tem alguma forma de limpar o cache de apenas um determinado comando?

Sim. Podemos utilizar o DBCC FREEPROCCACHE passando o [sys.dm_exec_cached_plans].PlanHandle, por ex:

SELECT cp.plan_handle, st.[text]
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st

O comando acima retorna o PlanHandle dos planos, depois e só passar ele como parâmetro para o FREEPROCCACHE

DBCC FREEPROCCACHE(0x06000500AF643E18B840C234000000000000000000000000)

Créditos para o GlennBerry.

Abraços

Categorias:SQL Server

Friends of Red-Gate, Sim, tbm sou!

1 de dezembro de 2009 5 comentários

Pessoal depois que vi o post do meu amigo Alex Rosa falando sobre o programa “Friends of Red-Gate” fiquei bem interessado no assunto já que as ferramentas da Red-Gate são muito úteis para quem trabalha com SQL Server, o SQL Prompt é uma verdadeira mão na roda.

Bom, primeiro agradeço ao Alex por me ajudar a conhecer o programa, e segundo, agradeço a Red-Gate por me conceder a honra de fazer parte do time de Amigos deles :-).

Se prepare porque com certeza você verá por ai alguns artigos do tipo, “SQL Server Intellisense vs Red-Gate SQL Prompt”

Você pode ler mais sobre o programa aqui.

image

Categorias:Não categorizado