Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Produzido por:
53:. Introdução ao Query Processor
Saiba mais sobre o responsável por calcular a
maneira mais eficiente de acesso aos dados
No SQL Server
www.codificando.net Por: Fabiano Neves Amorim
Editorial
Mais um ano de muitas conquistas se acabou, e um novo ano cheio de novidades começa agora!
Em 2009 a equipe da revista foi sensacional, o nosso time está cada vez mais forte e profissionalizado.
Cada um dos integrantes é peça fundamental no nosso trabalho na revista, e seu trabalho é muito
importante para que possamos entregar esse conteúdo para vocês!
Neste ano de 2010, muitas ferramentas do nosso mundo serão lançadas em RTM nos possibilitando ter
mais agilidade nas atividades e ganho de tempo em nosso dia-a-dia. Tenho certeza que muitos de nós
conquistarão patamares que estão sendo galgados a tempos, realizando sonhos e desafios que ficaram
pendentes de 2009.
Neste ano, teremos o lançamento oficial do Visual Studio 2010, do Windows Azure, do Office 2010,
SharePoint 2010 e algumas outras ferramentas... Viram só quantas novidades teremos agora?! E como nós
do Codificando .Net sempre fazemos, montaremos eventos presenciais e on-line para poder mostrar à
vocês estas novas ferramentas e novidades da nossa área.
Quero deixar um agradecimento especial à todos que nos acompanham, lendo esse material, e aos nossos
colaboradores que dispendem de tempo valioso pra ajudar a divulgar tecnologia, escrevendo! Não poderia
esquecer, de forma alguma, do time de profissionais que fazem esse trabalho acontecer, o time de editores
da revista.
Valeu gente.
Diego Nogare
site@codificandomagazine.net
e-magazine
Codificando.net e-magazine
Figura 6: E-Mail de confirmação do Azure
Diego Nogare
Graduado em Ciência da Computação, Pós-Graduado em Engenharia de Computação com ênfase em Desenvolvimento
Web com .NET. Colaborador do Portal Linha de Código e da revista SQL Magazine, Líder do grupo de usuários
Codificando .NET, Líder dos Microsoft Student Partners [MSP] de São Paulo e Microsoft Most Valuable Professional
[MVP] em SQL Server, possui certificações MCP e MCTS em SQL Server 2005, é palestrante em eventos da Microsoft,
Codificando .NET e INETA BR, mantém o site: www.diegonogare.net.
No primeiro artigo sobre SAD (http:// onde será inserido o código. Após a
www.linhadecodigo.com.br/Artigo.aspx? inserção do código válido no site e
id=2493), foi explicado superficialmente o clicando em “Submit” é necessário
que é o SQL Azure Database e como criar aceitar os termos de uso clicando em “I
nossa conta na nuvem. Depois de receber o Accept”. Após este passo, vamos definir
e-mail de confirmação, que pode demorar as credenciais de acesso à nossa base do
alguns dias para chegar, vamos nos SQL Azure Database, veja a Figura 2. A
conectar ao SAD e começar de fato a partir deste momento, o SAD se
trabalhar na nuvem. comportará parecido como uma
instancia do SQL, podendo realizar
Os pré-requisitos para trabalhar nestes quase todas as atividades que se faz em
exemplos são poucos. Basicamente é uma instância local.
necessário aquele e-mail de confirmação
com seu código de validação do Azure,
uma conta ativa na LIVE, e também ter
alguma versão do SSMS 2008 (SQL Server
Management Studio 2008). Neste caso,
utilizaremos a versão Express que pode ser Codificando.net e-magazine
baixada gratuitamente aqui: http://
www.microsoft.com/downloads/
details.aspx?
displaylang=en&FamilyID=08e52ac2-1d62-
45f6-9a4a-4b76a8564a2b
Diego Nogare
Graduado em Ciência da Computação, Pós-Graduado em
Engenharia de Computação com ênfase em
Desenvolvimento Web com .NET. Colaborador do Portal
Linha de Código e da revista SQL Magazine, Líder do
grupo de usuários Codificando .NET, Líder dos Microsoft
Student Partners [MSP] de São Paulo e Microsoft Most
Valuable Professional [MVP] em SQL Server, possui
certificações MCP e MCTS em SQL Server 2005, é
palestrante em eventos da Microsoft, Codificando .NET e
INETA BR, mantém o site: www.diegonogare.net.
Codificando.net e-magazine
Quando nos conectamos através do SSMS Já que estou conectado na base de dados
(SQL Server Management Studio) ao Master (que é a única base de dados que
SAD, precisamos nos atentar à alguns tenho no momento), vou criar um novo
detalhes por se tratar de uma versão CTP. Database pra exemplificar o restante do
Por exemplo, a forma de se conectar e em artigo. Vou utilizar uma sintaxe básica
qual banco de dados será. Por padrão, (create database dbLinhaDeCodigo
quando nos conectamos ao SAD através ) pra criar o banco (1) e vou conferir no
do SSMS, fazemos a conexão à base serviço on-line do Azure (2), para Codificando.net e-magazine
Master, para exemplificar alguns assegurar que realmente está lá. Confira
detalhes, vou abrir uma instância do a Figura 2, estes itens.
SSMS 2008 Express e me conectar ao
banco de dados default do meu SAD, e
após a conexão vou verificar todos os
Databases criados lá no meu servidor na
nuvem. Esta consulta pode ser
acompanhada na Figura 1.
Diego Nogare
Graduado em Ciência da Computação, Pós-Graduado
em Engenharia de Computação com ênfase em
Desenvolvimento Web com .NET. Colaborador do
Portal Linha de Código e da revista SQL Magazine, Líder
do grupo de usuários Codificando .NET, Líder dos
Microsoft Student Partners [MSP] de São Paulo e
Microsoft Most Valuable Professional [MVP] em SQL
Server, possui certificações MCP e MCTS em SQL Server
2005, é palestrante em eventos da Microsoft,
Codificando .NET e INETA BR, mantém o site:
www.diegonogare.net.
Codificando.net e-magazine
Codificando.net e-magazine
Codificando.net e-magazine
Diagram, para criar a classe Clientes da
Crie mais esses métodos seguindo os
maneira que aprendemos na primeira
passos acima:
parte deste artigo:
Codificando.net e-magazine
encontra referências para aprofundar os
conhecimentos sobre o mesmo.
Alterar Obter
Listar
Codificando.net e-magazine
Felipe Pocchini
Codificando.net e-magazine
Universidade José do Rosário Vellano (UNIFENAS), em
Alfenas – MG, trabalha com desenvolvimento de
aplicações Web e Windows Forms utilizando a
tecnologia .Net. Moderador da comunidade
Desenvolvendo para Web, colaborador da comunidade
Codificando.Net e editor da revista eletrônica
Codificando .Net e-Magazine.
Codificando.net e-magazine
viável mesmo dispondo do FileStream.
Em seguida vamos criar a nossa tabela FONTE: livro Microsoft SQL Server 2008 -
Codificando.net e-magazine
Utilizando a propriedade
Identity_Insert e DBCC
Por: José Heberton Vilela de Melo
Codificando.net e-magazine
um banco de dados, colunas que são 3 Nome3 2009-09-23
auto incremento. Estas, são definidas 4 Nome4 2009-09-23
pela propriedade IDENTITY com os seus Figura 1. Entidade com a coluna auto
respectivos valores seqüenciados. incremento.
1 Nome1 2009-09-23
Entretanto, para que nenhum intervalo
2 Nome2 2009-09-23
seja criado ou para preencher um 5 Nome5 2009-09-23
intervalo existente causado por uma
6 Nome6 2009-09-23
exclusão, poderemos avaliar os valores
Figura 2. Entidade com valores identidades fora
de seqüência.
Agora, observe que a nossa entidade registros e inserir mais dois novos
possui um intervalo entre o segundo e o registros.
terceiro registro. Isso é totalmente
-- REMOVENDO 2 REGISTROS DA
desagradável para quem gosta de manter ENTIDADE #TbIdentity
seus registros organizados na sua base de
DELETE FROM #TbIdentity WHERE
dados. Para corrigirmos esse tipo de IdCliente > 2
problema, demonstrarei dois exemplos -- INSERINDO DOIS NOVOS REGISTROS
que ajudarão a reorganizar os registros da INSERT INTO #TbIdentity
coluna IdCliente. (NoCliente, DaCadastro)
VALUES ('Nome5',GETDATE
())
-- CRIANDO UMA ENTIDADE TEMPORARIA ,('Nome6',GETDATE())
CREATE TABLE #TbIdentity
( Nesse ponto, teremos a seguinte situação
IdCliente INT IDENTITY(1,1) na entidade temporária, conforme figura
PRIMARY KEY
,NoCliente VARCHAR(35) NOT NULL 4.
,DaCadastro DATE
DEFAULT(GETDATE()) IdCliente NoCliente DaCadastro
) 1 Nome1 2009-09-23
GO 2 Nome2 2009-09-23
5 Nome5 2009-09-23
6 Nome6 2009-09-23
Nesse momento, teremos a seguinte Vale lembrar que somente uma tabela em
situação na entidade temporária, conforme uma sessão poderá ter a propriedade
figura 3. IDENTITY_INSERT definida como ON.
IdCliente NoCliente DaCadastro Isso quer dizer que, se uma entidade
1 Nome1 2009-09-23 estiver com a propriedade definida como
2 Nome2 2009-09-23 ON e uma instrução SET
3 Nome3 2009-09-23
4 Nome4 2009-09-23
IDENTITY_INSERT ON for emitida para
outra entidade, o SQL Server retornará
Figura 3. Entidade temporária com coluna auto
incremento. uma mensagem de erro informando que
SET IDENTITY_INSERT já está definido
Agora, vamos excluir os dois últimos como ON.
-- DEFININDO A PROPRIEDADE
IDENTITY_INSERT PARA ON -- INSERINDO NOVOS REGISTROS AINDA
COM A PROPRIEDADE DEFINIDA PARA ON
SET IDENTITY_INSERT #TbIdentity ON
O valor default desta propriedade INSERT INTO #TbIdentity
é OFF, e é preciso específicar o (IdCliente ,NoCliente, DaCadastro)
nome da tabela na qual irá receber VALUES (10,'Nome10',GETDATE())
o valor da propriedade.
O Paradigma FILLFACTOR
De uma certa maneira ele não estava A verdade com 100% de FillFactor
errado e eu, particularmente, adorei o Simplificando:
"pulando feito pipoca". Mas, sinceramente, John, Robert, Phil, Luca, Lucy, Chloe,
essa era uma resposta que eu preferia não Hannah and Julia decidiram ir à praia.
ter ouvido. Imagine se fosse alguém do John era o organizador e resolveu
Storage Team... colocar homens em um carro e mulheres
em outro. Um dia antes da viagem, Luca
O que é Page Split? resolveu não ir e Richard foi convidado.
O layout ficou parecido com a figura 1 :
Nós sabemos que o SQL SERVER trabalha
com páginas de 8kb e cada página possui
um fator de preenchimento, chamado
fillfactor. Por default este fator é 0, ou seja,
página totalmente preenchida e sem
espaço livre para novos registros.
Quando um registro é inserido ou
atualizado, este registro tem que ser
armazenado no espaço da página. Se a
página não possui espaço livre, o SQL
Server precisa reorganizar todas as
páginas para armazenar o novo registro.
Mas estas novas páginas não são
contínuas.
Figura 1 – Layout sem espaço no carro.
if object_id('Testfillfactor')
is not null
drop table Testfillfactor
go
if object_id
('Testfillfactor') is not
null
drop table Testfillfactor
go
create table Testfillfactor
( id int not null,
Figura 11 – Representação Fillfactor 30%.
Codificando.net e-magazine
name char(2000)
)
create unique clustered index Uma página de dados foi criada, mas
PK_TestFill on Testfillfactor com o mesmo número de linhas com o
(id)
FillFactor de 100%
WITH( PAD_INDEX = OFF,
FILLFACTOR = 30, Como podemos ver:
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, Três Páginas de Dados (Data Pages)
ALLOW_ROW_LOCKS = ON, Coluna PageType = 1, que são as páginas
ALLOW_PAGE_LOCKS = ON
) 7430,7406 e 7408;
ON [PRIMARY]
go Uma Página de Índice (Index Page)
(PrevPageID) = 0
Como a coluna m_slotCnt me informa o
02. Página 7406 número de linhas que esta página tem (2)
e a coluna m_freeCnt o número de bytes
♦ Próxima Página de dados livres na página, minha conta novamente
(NextPageID) = 7408 está correta. E outra, a página 7406, terá
♦ Página de Dados Anterior os IDs 5 e 7, e a página 7408 o ID 9.
(PrevPageID) = 7430
Podemos executar este script para
03. Página 7408 visualizar esta afirmação:
Codificando.net e-magazine
[Field]
Com eu criei a coluna fixa (char 2000) varchar(max),
[Value]
devemos ter na página 7430 duas linhas , varchar(max)
que seriam o ID 3 e 5. Lembre-se que o )
insert into #dbccpageresults exec
índice cluster sobre o ID. ('dbcc page( 0, 1, 7430, 3 ) with
tableresults')
Verifcando (figura 12): go
select 'PAGE 7430',* from
dbcc page( 0, 1, 7430, 3) #dbccpageresults where [field] =
'id'
go
truncate table #dbccpageresults
go
go
select 'PAGE 7430',* from
#dbccpageresults where [field] =
'id'
go
truncate table #dbccpageresults
go
Figura 13 – Script para visualizar informações
insert into #dbccpageresults exec
das páginas.
('dbcc page( 0, 1, 7406, 3 ) with
tableresults')
go
Ou: select 'PAGE 7406',* from
#dbccpageresults where [field] =
'id'
Figura 16 – Script visualizar informação sem page Figura 18 – Visualização das Páginas.
splits.
name6 varchar(1000),
Não tem mágica. É matemática pura.
name7 varchar(1000),
Temos espaço em cada página para
acomodar os dados novos! name8 varchar(1000),
)
create unique clustered index
O Paradigma FillFactor III - Índice PK_TestFill on Testfillfactor(id)
Cluster+Identity = 100% FillFactor sem WITH( PAD_INDEX = OFF,
Page Splits? FILLFACTOR = 100,
STATISTICS_NORECOMPUTE =
OFF,
É comum encontrarmos em fóruns a IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
seguinte pergunta (ou parecida com ela): ALLOW_PAGE_LOCKS = ON
"tenho um CIX (clustered index) no )
campo identity. Posso deixar com ON [PRIMARY]
go
FillFactor de 100%?". E a resposta
tradicional: "Sim. Já que os dados são set nocount on
declare @loop int
inseridos no final da página, não haverá set @loop = 1
page splits". while @loop < 50
begin
insert into TestFillfactor
A resposta correta na verdade é (name1,name2,name3,name4,name5
DEPENDE. ,name6,name7,name8)
values ('Name 1 ' +
convert(char(10),@loop),'Name
Depende dos tipos de colunas que terão 2 ' + convert(char
sua tabela e, principalmente, se elas terão (10),@loop),'Name 3 ' +
convert(char(10),@loop),
atualizações no tamanho do seu conteúdo 'Name 4 ' + convert(char
(varchar, nvarchar, varbinary). (10),@loop),'Name 5 ' +
convert(char(10),@loop),'Name
6 ' + convert(char
Codificando.net e-magazine
Page Split ocorre no update também. (10),@loop),'Name 7 ' +
Vamos lá? convert(char(10),@loop),
'Name 8 ' + convert(char
(10),@loop))
if object_id('Testfillfactor') is set @loop = @loop + 1
not null end
drop table Testfillfactor go
go
Criamos uma tabela com tipos de dados
create table Testfillfactor
( id int identity(1,1) not variante. Reparem que os campos nome
null, são varchar. Populamos com 50 linhas
name1 varchar(1000), contínuas (identity , com CIX no campo
ID). Teoricamente não haveria Pages
name2 varchar(1000),
Splits.
name3 varchar(1000),
name4 varchar(1000),
Será?
Figura 22 – Visualização das Páginas. Agora sim! Ou seja da página 7548 pulou
para a página 8174 para continuar a
Errado! ordem do CIX (clustered index)!
Codificando.net e-magazine
insert e update, mas também esta tabela Exemplo de ótimas leituras:
tem muito select, pois alimenta um
relatório muito importante pra sua Inside Microsoft SQL Server 2005: T-SQL
organização e é chamada muitas vezes ao Querying
dia... Neste caso, reindexar ONLINE (ou
reorganizar) mais vezes este índice pode Inside Microsoft SQL Server 2005: The
ser mais vantajoso. Storage Engine
Eu tenho certeza disso? Claro que não. Inside Microsoft SQL Server 2005: Query
Tuning and Optimization
Mas eu faço algumas coisas que me
E os mesmos livros no SQL SERVER 2008
ajudam na análise e definição da solução: Não tenha medo de dizer "eu não sei, mas
Analise a carga de seus índices vou ver e aprender". Isso é muito melhor do
separadamente (cada um deles tem uma que dizer "eu não sei... sempre foi assim...
caraterística diferente) aprendi assim". Na verdade você esta
Conclusão
Até a próxima!
Laerte Junior
Codificando.net e-magazine
SQL SERVER, fascinado por códigos e scripts, escreve
artigos para MCDBABrasil, Imasters e Simple-Talk aonde
possue um blog também.
Laerte Junior
$hell Your Experience
www.laertejuniordba.spaces.live.com
www.simple-talk.com/community/blogs/laerte/
www.twitter.com/laertejuniordba
Relatório tabular
Codificando.net e-magazine
Figura 1 – Datatable Produtos Estoque.
Nesse exemplo criaremos um relatório
que nos permite visualizar a relação de Esse datatable será preenchido com os
produtos, suas respectivas categorias, total dados provenientes do resultado da
em estoque e valor unitário. O usuário seguinte stored procedure:
desse relatório pode selecionar uma ou getProdutosinCategorias, que recebe
mais categorias de produtos que deseja como parametro uma string com as
visualizar. O relatório faz uso de identificações das categorias separadas
formatação condicional para destacar as por vírgula.
quantidades em estoque se esse for
inferior a 250, também faremos uso dos Segundo Passo: Criação e
recursos de formatação de moeda e modelagem do Relatório
ordenação da coluna: “Nome do Incluiremos um novo relatório em nosso
Datatable no DataSet
Codificando.net e-magazine
rptViewMasterDetail.RefreshReport
configuração do reportViewer criado. A ();
seguir apresentamos um trecho do código
Os dados do relatório “detail” são
para carga das duas datatables e carregados com a tabela ItensPedido
configuração do reportViewer. A primeira do dataSet, e são configurados no
evento de processamento do
instrução (em vermelho) carrega a tabela subReport que é acessível através
Pedido e a segunda a ItensPedido. Vemos do delegate
SubreportProcessingEventHandler que
também que só configuramos o é assinado no construtor da classe
datasource do relatório “master”, e o da aplicação com a seguinte
relatório “detail” ? A seguir: instrução:
rptViewMasterDetail.LocalReport.Sub
reportProcessing += new
cmdReport.CommandType = SubreportProcessingEventHandler
CommandType.Text; (SubReportDetailProcessing);
cmdReport.Connection = conReport; Em seguida implementamos o método
cmdReport.CommandText = "SELECT SubReportDetailProcessing com as
[ped].ID_PEDIDO, seguintes instruções:
Criando o relatório
rptViewGrafico.LocalReport.ReportPa
Nosso relatório também exibe o período th = "..//..//Reports//
GrVendas.rdlc";
da consulta que é exibido na sessão ReportParameter[] parPeriodo =
header do relatório. Para recuperar essas { new ReportParameter
("dtInicio",txtDtInicio.Text), new
informações fornecidas pelo cliente ReportParameter
recorremos aos parâmetros, dtInicio e ("dtFim",txtDtFim.Text)};
rptViewGrafico.LocalReport.SetParam
dtFim, esta configuração é feita nas eters(parPeriodo);
propriedade do relatório , tab Parameters. ReportDataSource rds = new
ReportDataSource();
Criando o Cliente rds.Name = "Grafico_Vendas";
rds.Value = dsReport.Tables[0];
rptViewGrafico.LocalReport.DataSour
Para configuração do cliente, adicionamos ces.Clear();
rptViewGrafico.LocalReport.DataSour
e configuramos um controle ces.Add(rds);
ReportViewer. Em seguida adicionamos o
rptViewGrafico.RefreshReport();
código cliente para carga do dataTable e
configuração do reportViewer criado. A Finalmente eis nosso relatório em ação:
seguir apresentamos um trecho do código
para carga da datatable e configuração do
reportViewer com destaque para
Codificando.net e-magazine
passagem dos parâmetros dtInicio e
dtFim.
cmdReport.CommandType =
CommandType.Text;
cmdReport.Connection = conReport;
cmdReport.CommandText = "SELECT
[VEN].NO_VENDEDOR, SUM
([ITE].QT_PRODUTO*[PRO].VL_PRECO)
as [Valor do Pedido] FROM
TB_PEDIDO [PED] INNER JOIN
TB_ITENS_PEDIDO [ITE] ON Figura 14 – relatório chart em ação
[PED].ID_PEDIDO = [ITE].ID_PEDIDO
INNER JOIN TB_PRODUTO [PRO] ON
[ITE].ID_PRODUTO = Relatório document map
[PRO].ID_PRODUTO INNER JOIN
TB_VENDEDOR [VEN] ON
[PED].ID_VENDEDOR = Nesse exemplo criaremos um relatório que
[VEN].ID_VENDEDOR WHERE CONVERT nos permite visualizar pedidos, seus
(SMALLDATETIME, [PED].DT_PEDIDO,
Codificando.net e-magazine
a torná-lo parecido ao exibido na imagem
acima. Para tal faremos uso de uma das
Figura 15 –datatable Peddo. propriedades mais poderosas das tabelas
que é a tab Groups. Essa propriedade nos
permite, como o nome diz, agrupar os
Esse datatable será preenchido com os
registros por um ou mais campos, similar à
dados provenientes do resultado da
cláusula GROUP BY do T-SQL. Na figura 16
seguinte instrução SQL:
percebe-se que fizemos dois agrupamentos,
SELECT [PED].ID_PEDIDO,
1 e 2, respectivamente pelos campos
[PED].ID_VENDEDOR, NO_VENDEDOR e ID_PEDIDO.
[VEN].NO_VENDEDOR,
[PED].DT_PEDIDO ,[pro].DS_PRODUTO, Começamos nossa configuração criando um
[ite].QT_PRODUTO, [pro].VL_PRECO
FROM TB_PEDIDO [PED] INNER JOIN relatório com os atributos acima,
TB_VENDEDOR [VEN] ON configurando-o como um relatório tabular,
[PED].ID_VENDEDOR =
Codificando.net e-magazine
correspondente ao nome do vendedor, no Em seguida adicionamos o código cliente
segundo sofisticamos com a criação de para carga do DataTable e configuração do
uma expressão que concatena uma string reportViewer criado. A seguir
com o campo de identificação do pedido. apresentamos um trecho do código para
Finalmente movemos os campos nome do carga da datatable e configuração do
vendedor e identificação do pedido para reportViewer com destaque para passagem
as linhas de cabeçalho dos seus dos parâmetros dtInicio e dtFim.
respectivos grupos.
cmdReport.CommandType =
CommandType.Text;
Outro elemento interessante em nosso cmdReport.Connection = conReport;
relatório, e muito comum em relatórios cmdReport.CommandText = "SELECT
[PED].ID_PEDIDO, [PED].ID_VENDEDOR,
com agrupamento, são totalizadores. No [VEN].NO_VENDEDOR, [PED].DT_PEDIDO,
nosso relatório, sumarizamos o total do [pro].DS_PRODUTO, [ite].QT_PRODUTO,
[pro].VL_PRECO FROM TB_PEDIDO [PED]
pedido em uma caixa de texto posicionada INNER JOIN TB_VENDEDOR [VEN] ON
Codificando.net e-magazine
Arquiteto Microsoft, palestrante, tecno-colunista e
rptViewGrafico.RefreshReport(); instrutor da treinando .net. MCP, MCAD, MCSD, MCTS e
MCPD. E fanático pela série Star Wars – “may the force be
Finalmente eis nosso relatório em ação: with you.”
Limitações
Início Ambiente
Escolher o melhor caminho para chegar Para melhor entendimento dos exemplos
a determinado lugar pode ser deste artigo criaremos uma tabela, com
considerado para muitos uma arte, isso alguns dados e uma visão, que servirão
porque sempre existem vários caminhos como base para os testes que serão
que levam ao mesmo destino. Executar apresentados. A Listagem 1 contém o
uma tarefa da forma mais eficiente script para criação destes objetos.
possível requer que o caminho O Script cria a tabela Funcionarios com
percorrido seja o melhor dentre as algumas informações (ID, Nome, Salário,
centenas de variáveis que podem Telefone e Cidade) e, em seguida, são
influenciar na escolha do melhor inseridos alguns registros. Logo após,
percurso. uma view (vw_Funcionarios) é criada. A
grosso modo, podemos dizer que Views
No SQL Server o responsável por são tabelas virtuais definidas por uma
calcular a maneira mais eficiente de consulta T-SQL. A nossa view, criada na
acesso aos dados é chamado de Query Listagem 1, retorna o nome e o salário de
Processor, ele é dividido em duas partes, todos os funcionários que ganham mais
o Query Optimizer e o Query Execution de R$ 900,00.
Engine. Veremos neste artigo como o Codificando.net e-magazine
Query Optimizer funciona e quais os CREATE TABLE Funcionarios(ID
Int IDENTITY(1,1) PRIMARY KEY,
passos necessários para execução de um Nome
comando T-SQL. VarChar(30),
Salario
Numeric(18,2),
Entender como funciona e como
Telefone VarChar(15),
interpretar o trabalho do Query Cidade
Optimizer é uma das melhores maneiras VarChar(80));
de aprimorar seus conhecimentos em INSERT INTO Funcionarios(Nome,
SQL Server. Esse conhecimento será de Salario, Telefone, Cidade)
VALUES('José', 850.30, '11-
grande valor quando você precisar fazer 55960015', 'São Paulo');
algum trabalho de tunning em banco de
INSERT INTO Funcionarios(Nome,
dados. Salario, Telefone, Cidade)
VALUES('Antonio', 950, '11-
81115544', 'São Paulo');
Codificando.net e-magazine
Sempre que uma view é referenciada em
uma consulta, o SQL Server acessa as
tabelas que contém os dados. Na Figura 2,
por exemplo, podemos visualizar que o mais rapidamente. Ao optar por este
SQL acessa a tabela Funcionarios para ler recurso, o SQL utiliza mais de um
os valores das colunas Nome e Salario. processador para executar uma consulta.
Outro passo será resolver os nomes e tipos Dessa forma, o gasto com recursos se
de objetos envolvidos na consulta. Pode torna maior, já que mais processadores
acontecer de haver um sinônimo para uma serão utilizados, porém, o tempo de
determinada tabela que está em outro retorno tende a ser menor comparado a
servidor. Quando isso acontece, o SQL execução em apenas um processador.
precisa identificar que este sinônimo faz Durante a fase de análise o Query
referência a um objeto que está em outro Optimizer realiza algumas tarefas, entre
banco de dados, e este banco pode estar elas: identificar todos os possíveis
até mesmo ligado a outro servidor argumentos de pesquisa que podem estar
utilizando um Linked Server. especificados na cláusula WHERE e
Após estas análises o Parse/Bind retorna verificar se existem Joins entre tabelas que
um binário chamado Query Processor devem ser otimizados. Baseado nestas
Tree, que é uma representação lógica dos informações, ele analisa quais as opções
passos necessários para a execução do de acesso aos dados, quais índices deve
comando SQL. O Query Processor Tree é utilizar, em qual ordem os Joins devem ser
enviado para o próximo passo da execução realizados e qual o melhor algoritmo de
da consulta, que é a análise do Query Join para cada operação.
Optimizer. Na análise do Query Optimizer também
É importante destacar que nem sempre um existe um processo chamado
comando é enviado para a análise do “Simplification”, que é executado logo no
Query Optimizer. Por exemplo, alguns inicio da otimização. Uma das tarefas do
comandos DDL, tais como o CREATE “Simplification” é conhecida como
Table, que são de definição das estruturas “Predicate PushDown”, onde ele tenta
dos dados, não têm necessidade de uma reescrever sua consulta jogando os
Codificando.net e-magazine
análise do Query Optimizer, pois só há argumentos de pesquisa para a cláusula
uma forma de o SQL executar esta where (veja a Listagem 2).
operação.
Quando o Query Optimizer recebe o SELECT * FROM Funcionarios
INNER JOIN Funcionarios AS
Query Processor Tree, ele dará inicio a Listagem 2. Consulta com argumentos de
uma série de análises a fim de encontrar pesquisa especificados no join
qual é a maneira mais eficiente de acessar Funcionarios2
os dados desejados. ON Funcionarios.ID =
Funcionarios2.ID
O Query Optimizer trabalha baseado no AND Funcionarios.Nome =
custo de cada operador de acesso a dados, 'Antonio'
WHERE Funcionarios.ID > 1
ou seja, ele tenta encontrar a maneira que
Com base na consulta da Listagem 2,
gastará menos recursos para retornar os
quando o comando for executado, durante
dados. Também é levada em consideração
a fase de Simplification, o SQL irá
a velocidade de execução da consulta, por
reescrever a segunda consulta deslocando
exemplo, ele pode decidir por utilizar
o argumento de pesquisa
paralelismo a fim de retornar os dados
Funcionarios2
ON Funcionarios.ID =
Funcionarios2.ID
WHERE Funcionarios.ID > 1
AND Funcionarios.Nome =
'Antonio' Figura 4. Execution Plan gerado pelo Query
Optimizer
Visualizando o Plano de
execução
Existem três maneiras de visualizar um
Figura 3. Query Optimizer. plano de execução: o modo gráfico, modo
texto e XML. Vamos analisar os dois
representação gráfica de como o Query modos mais utilizados para análise:
Optimizer funciona. Como pode ser visto, gráfico e texto.
o resultado da análise será o Query Plan, Para visualizar o plano de execução em
ou plano de execução. modo gráfico, basta digitar um código T- Codificando.net e-magazine
Na Figura 4 podemos visualizar a SQL no SQL Server Management Studio e
representação gráfica de um plano de pressionar ctrl+l. Neste modo diversas
execução simples. informações complementares são exibidas.
Com base na estrutura da tabela Estas informações são chamadas de hints.
Funcionarios, podemos verificar na Figura Os hints contêm informações importantes
4 que para o comando SELECT * FROM sobre o objeto que está sendo acessado ou
Funcionarios, o Query Optimizer gerou sobre a operação que será executada, por
um plano de execução que acessa a tabela exemplo, dados sobre a utilização de
Funcionarios utilizando o operador memória, CPU e custo de execução de
Clustered Index Scan. cada operador dentro de todo o plano de
Durante a criação de uma tabela o SQL execução. Também são apresentados
Server automaticamente cria um índice dados informando se o resultado do
clustered para as colunas definidas como operador está ordenado ou não, número
primary key. Este é o comportamento estimado de linhas que serão retornadas e
Codificando.net e-magazine
execução é utilizando o modo texto. Para
habilitar a exibição do plano de execução
neste modo é necessário ativar uma das
Figura 5. Hint com dados do plano de execução. opções de ShowPlan, são elas:
Codificando.net e-magazine
[Expr1003]), DEFINE:([Expr1003]
Este plano é exatamente o mesmo que =CONVERT_IMPLICIT(varchar(30),
visualizamos na representação gráfica da [@1],0)), WHERE:( [dbo].
[Funcionarios].[ID]
Figura 4. Ele representa uma simples =CONVERT_IMPLICIT(int,[@2],0)))
leitura dos dados da tabela Funcionarios,
utilizando operador Clustered Index Scan,
que acessa o índice Operadores
PK__Funciona__3214EC277D430130.
Os ícones que são exibidos nos planos de
Na Listagem 5 podemos visualizar um execução (Figura 6) são conhecidos por
plano de execução em modo texto para um operadores. Eles são os responsáveis por
update na tabela Funcionarios. Observe executar as operações necessárias para
que o texto apresentado contém muitas rodar um comando T-SQL.
funções de processos internos do SQL Existem diversos operadores e ao longo
Server, o que acaba fazendo com que o dos artigos sobre o Query Optimizer
plano fique complexo de entender. veremos mais alguns deles. Dessa forma,
Codificando.net e-magazine
para agrupar todos os clientes em uma verdadeiro a linha é retornada no
linha e calcular o SUM da quantidade de output. Este processo se repete até o
pedidos. fim da leitura da tabela do Join;
Como já mencionado, para produzir o ♦ Já os operadores “blocking”
melhor plano de execução o Query necessitam primeiro ler todas as
Optimizer analisa qual é o melhor tipo de linhas (normalmente no método
operador para executar determinada Open()) do input para depois retorná
tarefa, tentando encontrar qual deles -las para o output. Um exemplo
executará o processo mais rápido e/ou clássico de operadores blocking é o
utilizando a menor quantidade de Sort, que necessita primeiro ler todas
recursos. as linhas do input para fazer a
Todo operador executa os métodos Open ordenação e, por fim, retornar as
(), GetRow() e Close(). Devido a esta linhas ordenadas.
característica, os operadores são
independentes, e, por isso, o SQL consegue Existem alguns cenários onde cada tipo de
gerenciá-los com maior facilidade. Como operador é melhor aproveitado, por
Codificando.net e-magazine
vantagem de encerrar o processo assim reutilizar o mesmo plano de execução
que encontrar alguma linha não seria para consultas semelhantes.
aproveitada. A área de memória utilizada para
Existem pouco mais de 100 operadores, armazenamento dos planos de execução é
entre eles: Scan, Compute Scalar, exatamente a quantidade de memória
Aggregate, Sort, Spools e Key Lookup, disponível para uso do servidor SQL
apresentados na Figura 6. Server. No SQL Server 7.0 havia uma área
Para finalizar esta seção é importante citar específica para o armazenamento dos
que não existe o melhor operador para planos, chamada “procedure cache”.
fazer um Join ou uma Agregação. Cada Porém, a partir da versão 2000 isso foi
operador é melhor para uma determinada alterado para que o SQL pudesse utilizar
situação. toda a memória disponível ao SQL Server.
Na verdade, no SQL Server 7.0 só eram
Cache armazenados planos de execução de
procedures (por isso se chamava
Como podemos observar, o processo de “procedure cache”), consultas ad-hoc não
Codificando.net e-magazine
reutilizado. plano de execução.
A coluna UseCounts retorna a quantidade Uma observação importante em relação ao
de vezes em que o plano de execução foi cache plan é que para consultas adhoc,
reutilizado. A coluna CacheObjType que não estejam parametrizadas (ou seja,
retorna o tipo do objeto em cache. Ela pode iguais a que utilizamos acima), para que o
apresentar os seguintes valores: Query Processor consiga fazer proveito do
plano que está em cache as consultas
♦ Compiled Plan: Representa um plano precisam ser escritas exatamente iguais.
de execução completo; Inclusive os valores no where terão que
♦ Compiled Plan Sub: Existe uma ser os mesmos. Repare que no exemplo da
propriedade do banco chamada Listagem 6 o SQL só reutilizou o plano de
“optimize for ad hoc workloads”. execução em cache porque a terceira
Quando habilitada, assim que uma consulta enviada para o servidor é
consulta AdHoc é enviada pela idêntica à primeira consulta, inclusive o
primeira vez ao SQL, ele grava um WHERE Nome = ‘José’.
Isso significa que cada caractere será
Nesta figura podemos observar que gráfico e modo texto. Por último foi
quando um mesmo comando for apresentado o conceito de Cache Plan e
executado, caso ele contenha um shell parametrização de consultas.
query no cache, o SQL pula uma etapa do
processo de localização do plano. Linked Server: É um mecanismo que
Observe na Tabela 2 que a linha 3 possui permite que o SQL Server execute
o plano de execução parametrizado, que é comandos em outro banco de dados OLE
o plano prepared. O plano prepared foi DB. Ao criar um linked Server o SQL cria
gerado baseado nas consultas executadas uma conexão com o banco de dados
pelo código da Listagem 7. Como destino, permitindo que os dados que
podemos observar, o SQL Server trocou o estão armazenados no banco destino sejam
valor no where por uma variável @1 e acessados a partir da própria instancia do
declarou a variável como datatype tinyint. SQL Server. Por exemplo, é possível abrir
Ao parametrizar uma consulta o SQL uma consulta no SSMS e fazer um update
tenta encontrar qual é a melhor opção de em uma tabela do SQL Server lendo os
variável a ser utilizada, neste caso, ele dados de uma base Oracle.
optou pelo tinyint por ela ocupar apenas 1 O banco utilizado no Linked Server pode
byte de armazenamento. ser remoto ou local. Podemos criar um
O datatype tinyint consegue tratar valores linked Server com um banco de dados
de 0 a 255, isto é, caso o valor informado Access, Oracle, MySQL, ou qualquer banco
no where seja 300 o SQL não conseguirá de dados que contenha um driver OLE DB.
utilizar este plano de execução, causando
uma nova recompilação do comando. OLE DB: (Object Linking and Embedding,
Na Figura 8 podemos visualizar como Database) é um pacote que contém as
funciona o conceito de parametrização. Ao informações necessárias para conexão e
parametrizar o valor de where Prikey, o gerenciamento da leitura dos registros
SQL consegue reutilizar o mesmo plano armazenados em uma fonte de dados
de execução para as três consultas apenas (arquivos txt, xls, entre outros) ou bancos
alterando o valor de “?”. de dados. Codificando.net e-magazine
Codificando.net e-magazine
Este artigo não tem como objetivo Este cenário é muito comum em sistemas
apresentar profundamente as questões internos (seja rodando na intranet ou internet).
técnicas sobre cada tecnologia e sim sobre o
ponto de vista de quais os melhores cenários As principais preocupações são:
para a aplicação delas. Para informações implementação dos requisitos de negócio,
técnicas, o site www.asp.net trás todo o segurança, performance de processamento,
conteúdo em diversos tipos de formatos infra-estrutura e distribuição. Dificilmente
(artigos, vídeos, passo-a-passo, etc). nesse cenário existe a figura de um designer.
www.codificando.net Abril
Dez//Maio
Jan -2009
2010 | 67
e-magazine
www.codificando.net Abril
Dez//Maio
Jan -2009
2010 | 68