Inicial > Não categorizado > Cuidado com Views…

Cuidado com Views…

 

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
  1. Nenhum comentário ainda.
  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: