Você está na página 1de 68

Sumrio

04,07 e 11 :. SQL Azure


Edio 13 Nmero 13 Ano 04 2010 EDITORES Alexandre Tarifa Diego Nogare Emerson Facunte Sergio Gonalves REVISO Felipe Pocchini Fernanda Sallai MONTAGEM / FORMATAO Milton Carvalhaes EDITORAO E DIAGRAMAO Adriano Almeida Fernanda Sallai COLABORADORES Caio Azevedo Diego Nogare Eduardo Bergantini Pint Felipe Pocchini Fabiano Neves Amorim Jos Heberton Vilela de Melo Laerte Junior
Introduo a SQL Azure Database, plataforma de bando de dados relacionais baseada em Nuvem.
Por: Diego Nogare

15:. Aplicaes com N camadas em ASP .Net - Parte II


Segunda parte do artigo, aplicando conceitos de camadas em ASP.Net
Por: Felipe Pocchini

20:. FileStream
Conhea esta nova feature do Microsoft SQL Server 2008
Por: Eduardo Bergantini Pint

23:. Utilizando a proprieadade Identity


Insert e DBCC CHECKIDENT
Conhea as propriedades entidades no banco de dados
Por: Jos Heberton Vilela de Melo

para

tratar

Fale com Editor


muito importante para a equipe saber a sua opinio sobre a revista, caso tenha alguma critica, sugesto, ou elogio entre em contato. Caso tenha interesse em publicar um artigo na revista envie o ttulo e um resumo do tema em formato Word.
site@codificandomagazine.net

28 :. O Paradigma FILLFACTOR
Veja um exemplo detalhado na utilizando conceitos deste paradigma.
Por: Laerte Junior

pratica

43:. SQL Reporting Service 2005 Parte III


Continuao do artigo explorando Microsoft SQL Reporting Service 2005
Por: Caio Azevedo

Produzido por:

53:. Introduo ao Query Processor


Saiba mais sobre o responsvel por calcular a maneira mais eficiente de acesso aos dados No SQL Server

www.codificando.net

Por: Fabiano Neves Amorim

03:. Editorial

67:. .Close ( )

Edio 13 Nmero 13 Ano 04 2010

Editorial
Mais um ano de muitas conquistas se acabou, e um novo ano cheio de novidades comea agora! Em 2009 a equipe da revista foi sensacional, o nosso time est cada vez mais forte e profissionalizado. Cada um dos integrantes pea fundamental no nosso trabalho na revista, e seu trabalho muito importante para que possamos entregar esse contedo para vocs! Neste ano de 2010, muitas ferramentas do nosso mundo sero lanadas em RTM nos possibilitando ter mais agilidade nas atividades e ganho de tempo em nosso dia-a-dia. Tenho certeza que muitos de ns conquistaro patamares que esto sendo galgados a tempos, realizando sonhos e desafios que ficaram pendentes de 2009. Neste ano, teremos o lanamento 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 ns do Codificando .Net sempre fazemos, montaremos eventos presenciais e on-line para poder mostrar vocs 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! No poderia esquecer, de forma alguma, do time de profissionais que fazem esse trabalho acontecer, o time de editores da revista. Um grande abrao e muitas conquistas em 2010! Famlia Codificando .Net" Valeu gente. Diego Nogare site@codificandomagazine.net

e-magazine

SQL Azure Database (Introduo) SQL Server 2008


Por: Diego Nogare

O SAD (SQL Azure Database) uma plataforma de banco de dados relacionais, baseado na nuvem. Este conceito de nuvem pode ser uma novidade para alguns, mas h algum tempo j vem sendo noticiado por muitas outras tecnologias, na Microsoft principalmente citado quando se fala em plataforma Azure. Computao na nuvem um conceito no qual os aplicativos e/ou servios ficam hospedados na web, no mais em um servidor local e proprietrio, e pode ser acessado normalmente pelos usurios da aplicao. um servio de alta disponibilidade que muitas grandes empresas de tecnologias esto investindo hoje em dia. Alguns benefcios que favorecem a expanso deste tipo de tecnologia na nuvem vo de escalabilidade, alta-disponibilidade at segurana com os recursos de proteo de dados atravs de infra-estrutura. Todos estes investimentos/gastos so de responsabilidades do provedor de servio que est disponibilizando a tecnologia na nuvem, diminuindo o gasto com hardware por parte da empresa que utilizar o servio. A Microsoft est apostando alto neste conceito de computao na nuvem, e a plataforma Azure uma prova viva disso (ou virtual, como queiram! rs). Uma das

reas de estudo dentro da plataforma Azure o SAD (SQL Azure Database, lembram), que como o nome j sugere, um banco de dados relacional hospedado na nuvem. Utilizar um servio na nuvem, no obriga voc a eliminar seu parque computacional local, pelo contrrio, alguns servios sero mais compensadores se utilizar o que j tem hoje em seu DataCenter. Na minha concepo, vamos utilizar o SAD quando uma aplicao precisar utilizar banco de dados e o cliente no tem o servidor de banco de dados local e nem quer comprar este servidor, neste caso a sada ideal seria utilizar o servio na nuvem. Mas quando uma empresa j tem o banco local, e tem infra-estrutura suficiente para rodar a aplicao localmente, no necessrio contratar os servios da Microsoft. S pra constar, estes DataCenters da Microsoft so bem grandes, por volta de uns 50Km cada um, e com vrios servidores blade virtualizados. Isso significa que provavelmente voc ter um servidor lgico rodando Windows Server 2008 e SQL Server 2008, mas a mquina fsica ser uma s (pra um
Dez / Jan- 2010

Codificando.net e-magazine
|

www.codificando.net

SQL Azure Database (Introduo) SQL Server 2008

e-magazine

monte de servidores lgicos). Depois desta historinha introdutria sobre o Azure, vamos nos conectar a nuvem! Primeiro passo a ser realizado para se trabalhar com o Azure se cadastrar no portal, aps este cadastro (que gratuito durante seu perodo de CTP) ser possvel acessar e estudar todos os servios Azure. Para fazer este cadastro ser necessrio ter em mos seu LiveID, que o mesmo e-mail e senha utilizados para acessar o HOTMAIL ou seu MESSENGER. Para realizar o cadastro acesse o link http:// portal.ex.azure.microsoft.com/ default.aspx e v at o item do Microsoft Connect (1) nesta pgina, ento siga os passos para se cadastrar gratuitamente. Aps o cadastro, volte a pgina inicial e acesse o item Sign Up (2), acompanhe na Figura 1 onde esto estes itens.

qualquer, que seja fcil para lembrar-se durante o desenvolvimento. Neste caso, foi utilizado SSDS-Sql-Magazine-Brasil. Logo mais embaixo tem uma caixa (3) que precisa ser marcada para avanar na criao da soluo. Aps preencher estes dois itens, clique em Create Soluction (4). Veja na figura 2 onde localizar estes processos.

Figura 2: Preenchendo os campos necessrios da soluo.

Figura 1: Localizando o Microsoft Connect no site.

Acessando o Sign Up ser possvel visualizar os recursos da plataforma Azure disponveis (1). Ento localize a caixa de texto que pergunta o nome da sua soluo (2). D um nome sugestivo

Aps esta etapa do processo, uma atualizao automtica da pgina acontecer e rolando a tela para baixo mostrar sua senha(2) para utilizao do servio. Dois detalhes importantes: Primeiro que o servio no ficar disponvel imediatamente, necessrio acessar um link (1) para validar a criao aps o cadastro e ento utilizar os servios da plataforma Azure. Segundo detalhe que as solues so nicas, logo no ser possvel criar outra soluo com o mesmo nome utilizado neste exemplo. Veja na Figura 3 onde localizar a senha gerada.

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan- 2010

SQL Azure Database (Introduo) SQL Server 2008

e-magazine

Figura 3: Senha informada pelo sistema.

Ao acessar o link de confirmao, uma mensagem de sucesso informada e sua soluo apresentada do lado direito da tela (1). Ao clicar sobre sua soluo, possvel gerenciar alguns itens, inclusive a alterao da senha. Para alterar a senha, necessrio acessar o item Solution Credentials (1) [Figura 4] e em seguida expandir o menu de Solution Password (1), na sequncia informe a nova senha e confirme (2) [Figura 5], por fim clique em Save (3) e se o resultado for satisfatrio a mensagem de que a senha foi atualizada com sucesso (4) deve aparecer. Acompanhe a Figura 4 e 5 para encontrar estes itens no site

Figura 5: Passos para alterao de Senha.

Depois do cadastro, e algum tempo pra validar seus dados, ser enviado um e-mail para seu endereo cadastrado, validando sua conta. O e-mail que enviado assinado pela conta ssdstlk@microsoft.com (libere ele em seu cadastro de spam), com o ttulo SQL Azure Invitation. Veja a figura 6, a caixa de entrada com o e-mail recebido. Neste e-mail, vem os passos a serem seguidos para se iniciar o trabalho com o Azure, passando um cdigo de validao e tambm alguns links para ajudar no seu desenvolvimento.

Codificando.net e-magazine

Figura 6: E-Mail de confirmao do Azure

Figura 4: Gerenciamento das solues.

Nesta primeira parte da sequncia de artigos sobre SAD, foi explicado um pouco sobre o servio na nuvem e como se cadastrar para utilizar o servio. O prximo artigo ser sobre como criar a primeira aplicao com o SAD hospedando nosso banco na nuvem.

Diego Nogare
Graduado em Cincia da Computao, Ps-Graduado em Engenharia de Computao com nfase em Desenvolvimento Web com .NET. Colaborador do Portal Linha de Cdigo e da revista SQL Magazine, Lder do grupo de usurios Codificando .NET, Lder dos Microsoft Student Partners [MSP] de So Paulo e Microsoft Most Valuable Professional [MVP] em SQL Server, possui certificaes MCP e MCTS em SQL Server 2005, palestrante em eventos da Microsoft, Codificando .NET e INETA BR, mantm o site: www.diegonogare.net.

www.codificando.net

Dez / Jan- 2010

e-magazine

Conectando ao SAD (SQL Azure Database) SQL Server 2008


Por: Diego Nogare

No primeiro artigo sobre SAD (http:// www.linhadecodigo.com.br/Artigo.aspx? id=2493), foi explicado superficialmente o que o SQL Azure Database e como criar nossa conta na nuvem. Depois de receber o e-mail de confirmao, que pode demorar alguns dias para chegar, vamos nos conectar ao SAD e comear de fato a trabalhar na nuvem. Os pr-requisitos para trabalhar nestes exemplos so poucos. Basicamente necessrio aquele e-mail de confirmao com seu cdigo de validao do Azure, uma conta ativa na LIVE, e tambm ter alguma verso do SSMS 2008 (SQL Server Management Studio 2008). Neste caso, utilizaremos a verso Express que pode ser baixada gratuitamente aqui: http:// www.microsoft.com/downloads/ details.aspx? displaylang=en&FamilyID=08e52ac2-1d6245f6-9a4a-4b76a8564a2b Lendo o e-mail de confirmao, temos as instrues, que inicia pedindo para nos conectarmos ao site https://sql.azure.com, utilizar nossa conta da LIVE para a primeira credencial e em seguida colocar o Invitation Code que foi fornecido atravs do e-mail. Veja a Figura 1, o site da Azure

onde ser inserido o cdigo. Aps a insero do cdigo vlido no site e clicando em Submit necessrio aceitar os termos de uso clicando em I Accept. Aps este passo, vamos definir as credenciais de acesso nossa base do SQL Azure Database, veja a Figura 2. A partir deste momento, o SAD se comportar parecido como uma instancia do SQL, podendo realizar quase todas as atividades que se faz em uma instncia local.

Codificando.net e-magazine
|

Figura 1: Local pra insero do Invitation Code.

www.codificando.net

Dez / Jan- 2010

Conectando ao SAD (SQL Azure Database) SQL Server

e-magazine

de bases de dados. Tambm possvel ver a string de conexo para acessar o SAD atravs de algum cliente do SQL e trabalhar remotamente. Veja a Figura 4, o que tem quando se clica no link Manage.

Figura 2: Credenciais para conexo ao SAD.

interessante manter a localizao como USA_Northwest pois estamos trabalhando com uma verso CTP, outra localizao pode ser que d algum resultado diferente.
Figura 4: Bases de dados na instncia criada.

Aps inserir os dados das credenciais, e clicar em Create Server, uma instncia do SQL ser criada nos servidores deles, e poderemos acessar a qualquer momento. Veja a Figura 3, a instncia criada.

Quando clicamos no boto Connection String, um pop-up aberto e as strings de acesso ao SAD so mostradas. s copiar a string do tipo de fonte que ser acessada a nossa instncia na nuvem, e ento trabalhar na nossa aplicao cliente preferida. Veja a Figura 5, as strings de conexes para a aplicao que criamos neste exemplo.

Codificando.net e-magazine

Figura 3: A instncia do SQL na nuvem

Para gerenciar nossas bases na instncia, podemos acessar o link Manage que est direita da tela e realizar a criao

Figura 5: String de Conexo da instncia.

www.codificando.net

Dez / Jan- 2010

Conectando ao SAD (SQL Azure Database) SQL Server

e-magazine

Agora que j temos a instncia criada, e a string de conexo. Vamos utilizar o SSMS 2008 Express pra acessar a nossa base na nuvem e trabalhar com o SQL Server hosteado pela Microsoft em seus DataCenters. Aps abrir o SSMS, por padro, j exibida a tela de login. Pelo SAD ainda ser uma verso CTP, ainda no possvel realizar a conexo por esta tela inicial, mas na verso RTM do SAD ser bem provvel que vamos conseguir conectar sem maiores problemas. Por no efetuar o login nesta tela, vamos clicar em Cancel (1) e em seguida em New Query (2). Acompanhe na Figura 6, a ordem a ser clicada e onde esto os botes.

voc criou e no campo Password fornea a senha criada. Aps isso, clique em Connect e o SSMS se conectar sua instncia na nuvem. Caso d algum erro de conexo, ser necessrio habilitar
o a conexo por TCP/IP no Configuration Manager.

Figura 7: Autenticao real ao SAD.

Figura 6: Forma de conexo ao Azure.

Outro ponto de ateno, por se tratar de uma verso CTP do SAD, um erro sempre apresentado ao se conectar com o SSMS. s clicar em OK e prosseguir com o estudo, como se nada tivesse acontecido. O erro est apresentado na Figura 8.

Codificando.net e-magazine

Aps clicar em New Query (item 2 da Figura 6), uma outra tela de login (que exibida na Figura 7) mostrada, se sua tela aparecer diferente desta apresentada no artigo, clique em Options >> no final da sua tela de login que ficar igual essa. Nos itens marcados de vermelho, insira os dados da string de conexo fornecidos, se precisar, consulte a Figura 5. No campo Server Name insira o endereo do seu servidor na nuvem, no campo Login coloque o usurio que

Figura 8: Erro aceitvel ao se conectar no SAD atravs do SSMS.

Agora que j est conectado ao servidor SQL hospedado na nuvem, pode-se fazer um teste simples consultando a verso do servidor SQL instalado. Fazendo uma busca no Azure (SELECT @@VERSION) possvel ter

www.codificando.net

Dez / Jan- 2010

Conectando ao SAD (SQL Azure Database) SQL Server

e-magazine

esse retorno. Veja a Figura 9.

Figura 9: Consulta ao servidor da nuvem

No prximo artigo sobre SAD, vamos criar um banco de dados atravs do SSMS e consultar no gerenciador web do Azure. Diego Nogare
Graduado em Cincia da Computao, Ps-Graduado em Engenharia de Computao com nfase em Desenvolvimento Web com .NET. Colaborador do Portal Linha de Cdigo e da revista SQL Magazine, Lder do grupo de usurios Codificando .NET, Lder dos Microsoft Student Partners [MSP] de So Paulo e Microsoft Most Valuable Professional [MVP] em SQL Server, possui certificaes MCP e MCTS em SQL Server 2005, palestrante em eventos da Microsoft, Codificando .NET e INETA BR, mantm o site: www.diegonogare.net.

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan- 2010

10

e-magazine

Criando primeiro DB com SAD (SQL Azure Database) SQL Server 2008
Por: Diego Nogare

Depois de nos cadastrarmos nos servios da Azure (http:// www.linhadecodigo.com.br/Artigo.aspx? id=2493) e fazer nossas conexes no SAD (http://www.linhadecodigo.com.br/ Artigo.aspx?id=2518), chegou a hora de criarmos o primeiro banco de dados e ver a interao entre a nuvem e uma aplicao cliente. Quando nos conectamos atravs do SSMS (SQL Server Management Studio) ao SAD, precisamos nos atentar alguns detalhes por se tratar de uma verso CTP. Por exemplo, a forma de se conectar e em qual banco de dados ser. Por padro, quando nos conectamos ao SAD atravs do SSMS, fazemos a conexo base Master, para exemplificar alguns detalhes, vou abrir uma instncia do SSMS 2008 Express e me conectar ao banco de dados default do meu SAD, e aps a conexo vou verificar todos os Databases criados l no meu servidor na nuvem. Esta consulta pode ser acompanhada na Figura 1.

Figura 1: Verificando os databases que temos na nuvem

J que estou conectado na base de dados Master (que a nica base de dados que tenho no momento), vou criar um novo Database pra exemplificar o restante do artigo. Vou utilizar uma sintaxe bsica (create database dbLinhaDeCodigo ) pra criar o banco (1) e vou conferir no servio on-line do Azure (2), para assegurar que realmente est l. Confira a Figura 2, estes itens.

Codificando.net e-magazine
|

Figura 2: Criao do banco de dados e verificao no

www.codificando.net

Dez / Jan- 2010

11

Criando primeiro DB com SAD (SQL Azure Database) SQL

e-magazine

Agora que j criamos uma nova base de dados no Azure, vamos ver os segredos para nos conectar ela. Como j dito algumas vezes, estamos em uma verso CTP do Azure ento pra realizar tarefas corriqueiras que fazemos de uma forma quando trabalhamos com um SQL Server qualquer, no Azure um pouco diferente! Por exemplo, pra conectar a algum database, necessrio informar na tela de login e no utilizando a sintaxe USE XXXXX ou alterando o combobox na IDE do SSMS, e esta conexo que faremos agora. Vamos para a tela de login de uma New Query (1), informamos o Server Name, Login e Password(2) e precisamos clicar em Options >>(3). Veja a Figura 3, estas opes.

Figura 4: Escolha do database nas opes de conexo.

Aps se conectar esta New Query do SAD, na base que criamos, vamos criar uma tabela e popular alguns registros l dentro. Veja o cdigo da criao da tabela na Listagem 1, e insero dos dados na Listagem 2.
CREATE TABLE tblArtigo (codigo INT IDENTITY NOT NULL ,titulo NVARCHAR(50) NOT NULL ,autor NVARCHAR(30) NOT NULL ,resumo NVARCHAR(100)) CREATE CLUSTERED INDEX idxTitulo ON tblArtigo(titulo)

Codificando.net e-magazine

Figura 3: Opes de conexo do SSMS

Aps clicar em Options >> est nosso segredinho, ser necessrio informar qual o banco de dados que a instncia se conectar, informe o campo nome dbLinhaDeCodigo no Connect to Database(1) e em seguida clique em Connect(2). Veja estes itens na Figura 4.

Vejam que necessrio criar um index clustered pra poder inserir dados na tabela, caso no tenham criado, uma mensagem de erro ser disparada e no persistir os dados.
INSERT INTO tblArtigo (titulo, autor, resumo) VALUES ('SAD - Criando Banco' ,'Diego Nogare'

www.codificando.net

Dez / Jan- 2010

12

Criando primeiro DB com SAD (SQL Azure Database) SQL

e-magazine

,'Neste artigo ser criado o primeiro banco em SAD...')

INSERT INTO tblArtigo (titulo, autor, resumo) VALUES ('LINQ com VS2010' ,'Andrey Sanches' ,'Por ser amante de Orientao Objetos, o LINQ me fez...')

Figura 6: Verificao das bases de dados existentes.

INSERT INTO tblArtigo (titulo, autor, resumo) VALUES ('Novidades do VB 2010' ,'Alexandre Tarifa' ,'Analisando o Roadmap do Visual Basic, podemos...')

Aps fazer algumas inseres, vou disparar um Select simples na tabela (SELECT *FROM tblArtigo ), pra constatar se os dados foram realmente inseridos e persistidos na nuvem. Pra visualizar os dados inseridos, veja a Figura 5.

Visto que agora j temos um database, uma tabela e alguns dados na nuvem, vamos remover este database criado. Atravs do gerenciador on-line do Azure, para mostrar que realmente existe uma integrao entre a nuvem e sua aplicao cliente. Aps a remoo da base, vamos novamente fazer uma busca, pra ver o que retorna. Acessando o gerenciador do Azure, selecionamos o radiobutton em frente ao nome da base de dados que desejamos remover e clicamos em Drop Database. Um pop-up de confirmao ser apresentado, aguardando sua autorizao para remover o referido banco de dados. Aps a confirmao, no existir mais a base que foi apagada. Veja o pop-up de confirmao na Figura 7.

Codificando.net e-magazine

Figura 5: Realizando um Select na nuvem

Voltando ao incio do texto, a primeira verificao que foi feita neste artigo foi consultar as bases que tnhamos no servidor. Vamos realizar a mesma validao de antes, mas agora sendo em algum momento aps a criao da nova database. Veja o resultado na Figura 6.

Figura 7: Pop-up de confirmao de excluso de base de dados.

www.codificando.net

Dez / Jan- 2010

13

Criando primeiro DB com SAD (SQL Azure Database) SQL

e-magazine

Se fizer novamente a primeira verificao que foi realizada, ser constatado exatamente o mesmo retorno, visto que no temos mais a base que foi criada, somente a MASTER. Aps realizar todos os exemplos deste artigo, pudemos ver como se conectar ao SAD e criar um database, uma tabela e alguns dados na nuvem. Aps isso, vimos como droparum banco de dados da nuvem e provar essa interao entre as partes. Diego Nogare
Graduado em Cincia da Computao, Ps-Graduado em Engenharia de Computao com nfase em Desenvolvimento Web com .NET. Colaborador do Portal Linha de Cdigo e da revista SQL Magazine, Lder do grupo de usurios Codificando .NET, Lder dos Microsoft Student Partners [MSP] de So Paulo e Microsoft Most Valuable Professional [MVP] em SQL Server, possui certificaes MCP e MCTS em SQL Server 2005, palestrante em eventos da Microsoft, Codificando .NET e INETA BR, mantm o site: www.diegonogare.net.

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan- 2010

14

e-magazine

Aplicaes em N Camadas com ASP .NET - PARTE II

Por: Felipe Pocchini

Aplicaes em n camadas so desenvolvidas de forma distribuda, onde cada camada tem sua responsabilidade dentro do contexto. Para um modelo de aplicao Web so comumente usadas 3 camadas: Presentation(Apresentao), Business(Lgica do negcio) e Data (Responsvel pelas transaes com o banco da dados). Para esta segunda parte do artigo, iremos criar a camada Data, que ser responsvel por todas as transaes com o banco de dados.

neste artigo. Uma de suas grandes vantagens que atravs dela, podemos mudar a qualquer momento nosso sistema de banco de dados, sem prejudicar a lgica do negocio. Para adicionar a camada ao projeto, vamos clicar com o boto direito na soluo e adicionar um novo projeto.

Codificando.net e-magazine

Figura 2: Adicionando um novo projeto a soluo (Add > New Project).

Figura 1: Exemplo de aplicao em N Camadas.

Esse novo projeto vai ser do tipo Class Library, pois aqui sero criadas somente as classes responsveis pela comunicao com o banco de dados.

Iremos adicionar a camada Data juntamente com a primeira parte criada

www.codificando.net

Dez/ Jan - 2010

15

Aplicaes em N Camadas com ASP .NET - PARTE II

e-magazine

A classe Clientes vai conter apenas um atributo e os mtodos responsveis pelas transaes SQL, j que nossa entidade foi definida na camada Entity. Como aprendemos na primeira parte deste artigo, vamos criar um atributo que ir receber a string de conexo com o banco de dados:
Figura 3: Projeto do tipo Class Library.

connectionString Este um atributo de uso exclusivo da classe Clientes, no sendo preciso criar uma propriedade para acess-lo, pois o mesmo j est encapsulado. Mais uma vez vamos contar com recursos do Visual Studio para facilitar nossa vida para a criao dos mtodos:

Com o projeto adicionado a soluo, podemos agora trabalhar na camada Data da qual receber uma entidade atravs da camada business, executando as transaes com o banco de dados.

Figura 4: Projeto criado. Figura 6: Adicionando mtodos na classe Clientes (Add > Method).

Vamos utilizar a opo View Class Diagram, para criar a classe Clientes da maneira que aprendemos na primeira parte deste artigo:

Codificando.net e-magazine

Crie mais esses mtodos seguindo os passos acima: Alterar, Excluir, Obter, Listar. O resultado final ser esse:

Figura 5: Visualizando o diagrama de classes da camada de Data (View Class Diagram).

Figura 7: Classe Clientes com todos os mtodos e atributos definidos.

www.codificando.net

Dez/ Jan - 2010

16

Aplicaes em N Camadas com ASP .NET - PARTE II

e-magazine

Para visualizar o cdigo da classe Clientes, basta dar um duplo clique na classe.

Agora vamos adicionar na classe Clientes os namespaces, System.Data e System.Data.SqlClient do Framework para trabalharmos com as classes do ADO.NET.

Figura 10: namespace System.Data e System.Data.SqlClient adicionados a classe

Vamos atribuir a string de conexo ao atributo connectionString.


Figura 11: atributo connectionString recebendo Figura 8: Visualizao do cdigo da classe Clientes

Como podemos ver na Figura 8, os mtodos da classe Clientes foram criados, porm no esto implementados. Neste caso, como o foco estudar aplicaes em n camadas, vamos agora implementar cada mtodo sem a preocupao de estudar ADO.NET, onde no final do artigo voc encontra referncias para aprofundar os conhecimentos sobre o mesmo. Para a camada Data reconhecer uma entidade da camada Entity, necessrio adicionar a referencia da camada Entity na camada Data.

Vamos implementar agora os mtodos da classe Clientes, acompanhe abaixo: Inserir

Codificando.net e-magazine

Figura 12: implementao do mtodo Inserir.

Figura 9: Adicionando referencia da camada Entity na camada Data (Add Reference > Projects > OK).

www.codificando.net

Dez/ Jan - 2010

17

Aplicaes em N Camadas com ASP .NET - PARTE II

e-magazine

Alterar

Obter

Figura 13: implementao do mtodo Alterar. Figura 15: implementao do mtodo Obter.

Excluir Listar

Codificando.net e-magazine

Figura 14: implementao do mtodo Excluir.

Figura 16: implementao do mtodo Listar.

Conclumos que ao final de mais uma etapa, teremos a classe Clientes definida juntamente com a camada finalizada. Na www.codificando.net

Dez/ Jan - 2010

18

Aplicaes em N Camadas com ASP .NET - PARTE II

e-magazine

terceira parte desse artigo vamos criar a camada de negcio (Business) que ficar responsvel pela comunicao e validao dos dados, entre a apresentao (Presentation) e a camada de dados (Data).

Participe desse artigo deixando seu comentrio. Aprofunde seus conhecimentos sobre esse tema na comunidade ASP.NET Aprofunde seus conhecimentos sobre esse tema na comunidade ADO.NET Para saber mais: Viso geral de aplicativo de dados n camadas ADO.NET At a prxima, grande abrao a todos. Felipe Pocchini

Felipe Pocchini
Graduado em Cincia da Computao pela Universidade Jos do Rosrio Vellano (UNIFENAS), em Alfenas MG, trabalha com desenvolvimento de aplicaes Web e Windows Forms utilizando a tecnologia .Net. Moderador da comunidade Desenvolvendo para Web, colaborador da comunidade Codificando.Net e editor da revista eletrnica Codificando .Net e-Magazine.

Codificando.net e-magazine
|

www.codificando.net

Dez/ Jan - 2010

19

e-magazine

FileStream, a nova feature do SQL Server 2008


Por: Eduardo Bergantini Pint

Entendendo o FileStream O SQL Server sempre proveu a capacidade de armazenar dados binrios, assim voc podia pegar qualquer tipo de arquivo e armazen-lo em uma coluna do tipo VARBINARY ( MAX ), no entanto um BLOB (Binary Large Object) tem um padro de usabilidade diferente de dados relacionais, que so concatenados por meio de I/O e armazenados como dados estendidos, no possvel fazer um streaming de um BLOB. Por causa dessa limitao, a soluo paliativa dos desenvolvedores era disponibilizar o arquivo em um diretrio e apenas indicar o caminho no banco de dados, que ainda sim uma soluo vivel mesmo dispondo do FileStream. Criando e utilizando o FileStream Por padro o FILESTREAM vem habilitado na instncia do SQL Server 2008, quando voc vai criar o seu banco de dados deve apontar para ele onde ficar a armazenado o diretrio do seu FileStream.
CREATE DATABASE [Teste] ON PRIMARY (NAME = N'Teste_Data', FILENAME = N'D:\Teste\data\Teste.mdf', SIZE = 8MB, MAXSIZE = UNLIMITED, FILEGROWTH = 16MB),

FILEGROUP FgTesteSave (NAME = N'Teste_Data2', FILENAME = N'D:\Teste\data_save\Teste.ndf', SIZE = 8MB, MAXSIZE = UNLIMITED, FILEGROWTH = 16MB), FILEGROUP FgTesteDocuments CONTAINS FILESTREAM DEFAULT (NAME = N'Teste_Documents', FILENAME = N'D:\Teste\document') LOG ON (NAME = N'Teste_Log', FILENAME = N'D:\Teste\log\Teste.ldf', SIZE = 8MB, MAXSIZE = 2048GB, FILEGROWTH = 16MB) GO

Codificando.net e-magazine

Figura 01: Diretrio de criao do FileStream antes de ser gerado

Na criao de um FileStream repare bem que voc deve apontar um diretrio e no um arquivo, dentro desse diretrio sero criados os arquivos para FileStream.

www.codificando.net

Dez / Jan - 2010

20

FileStream, a nova feature do SQL Server 2008

e-magazine

que ser responsvel pelo armazenamento desses arquivos.


CREATE TABLE [dbo].[TestarMedia] ( [testeID] UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL PRIMARY KEY, [dataCriacao] DATETIME NOT NULL DEFAULT (GETDATE()), [criadoPor] NVARCHAR(255) NOT NULL, [fileName] NVARCHAR(255) NOT NULL, [tipoTeste] NVARCHAR(255) NOT NULL, [localizacao] GEOMETRY NULL, [arquivo] VARBINARY(MAX) FILESTREAM); GO

Figura 02: Diretrio do FileStream criado pelo SQL Server 2008

Mas e nos casos em que o banco de dados ainda no tem FileStream? Nesse caso voc utilizaria o seguinte cdigo, para dizer ao seu banco de dados criar a estrutura de FileStream:
ALTER DATABASE [Teste] ADD FILEGROUP FgTesteDocuments CONTAINS FILESTREAM GO ALTER DATABASE [Teste] ADD FILE ( NAME= 'fs_filestream', FILENAME = N'D:\Teste\document' ) TO FILEGROUP FgTesteDocuments GO Alterando o banco de dados para aceitar FileStream

Figura 03: Criando uma tabela para utilizar o novo recurso

Colunas utilizando o FileStream requerem a propriedade ROWGUILDCOL, ela serve para o sistema de armazenamento manter traado a instncia do banco no filesystem. Um dos pontos positivos de utilizar o FileStream para armazenar seus arquivos que, por estar dentro do SQL Server voc no ter problema com perda de dados ou corrupo de dados, a menos que tenha ocorrido na hora de ser inserido, podendo assim recuperar seus dados em caso de catastrofes realizando um simples restore no banco. FONTE: livro Microsoft SQL Server 2008 -

Codificando.net e-magazine

A primeira vez que voc for para o diretrio document, voc encontrar alguns arquivos NTFS com GUID's como nome, e alguns arquivos principais com arquivos de log. Todo esse funcionamento serve para criar o namespace do FileStream. Em seguida vamos criar a nossa tabela

www.codificando.net

Dez / Jan - 2010

21

FileStream, a nova feature do SQL Server 2008

e-magazine

Implementation and Maintenance Eduardo Bergantini Pint


Desenvolvedor .Net 2 anos pela empresa MinhaVida (www.minhavida.com.br). Com nfase em aplicativos web de alta performance membro e colaborador da comunidade codificando.net.

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan - 2010

22

e-magazine

Utilizando a propriedade Identity_Insert e DBCC


Por: Jos Heberton Vilela de Melo

Nesse artigo, farei uma breve demonstrao sobre a propriedade Identity_Insert, utilizada para permitir a insero de valores explcitos na coluna de identidade de uma tabela. Demonstrarei tambm a utilizao do DBCC CHECKIDENT que serve para verificar o valor de identidade atual para a tabela especificada e, se necessrio, altera o valor de identidade. Onde tambm possvel usar o DBCC CHECKIDENT para definir manualmente um novo valor de identidade atual de uma coluna identidade. comum, encontramos em entidades de um banco de dados, colunas que so auto incremento. Estas, so definidas pela propriedade IDENTITY com os seus respectivos valores seqenciados. Geralmente, quando executamos eventos de excluso de registros nas entidades, acaba se gerando intervalos indesejveis. Se esta for uma preocupao, no utilize a propriedade IDENTITY. Entretanto, para que nenhum intervalo seja criado ou para preencher um intervalo existente causado por uma excluso, poderemos avaliar os valores

de identidade existentes, antes de inserir valores explicitamente. Poder surgir o seguinte questionamento: Inserir valores manualmente em uma coluna que auto incremento? Sim. Isso mesmo. Ser possvel realizar, utilizando a propriedade SET IDENTITY_INSERT definida para ON. Digamos que criamos uma entidade com uma coluna que ser auto incremento. Inserimos 4 registros nela e teremos a seguinte populao na entidade, conforme figura 1.
IdCliente 1 2 3 4 NoCliente Nome1 Nome2 Nome3 Nome4 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Codificando.net e-magazine

Figura 1. Entidade com a coluna auto incremento.

Agora, se excluirmos os dois ltimos registros e inserirmos dois novos registros, teramos a seguinte populao na entidade conforme figura 2.
IdCliente 1 2 5 6 NoCliente Nome1 Nome2 Nome5 Nome6 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Figura 2. Entidade com valores identidades fora de seqncia.

www.codificando.net

Dez / Jan - 2010

23

Utilizando a propriedade Identity_Insert e DBCC CHECKIDENT

e-magazine

Agora, observe que a nossa entidade possui um intervalo entre o segundo e o terceiro registro. Isso totalmente desagradvel para quem gosta de manter seus registros organizados na sua base de dados. Para corrigirmos esse tipo de problema, demonstrarei dois exemplos que ajudaro a reorganizar os registros da coluna IdCliente.
-- CRIANDO UMA ENTIDADE TEMPORARIA CREATE TABLE #TbIdentity ( IdCliente INT IDENTITY(1,1) PRIMARY KEY ,NoCliente VARCHAR(35) NOT NULL ,DaCadastro DATE DEFAULT(GETDATE()) ) GO

registros e registros.

inserir

mais

dois

novos

-- REMOVENDO 2 REGISTROS DA ENTIDADE #TbIdentity DELETE FROM #TbIdentity WHERE IdCliente > 2 -- INSERINDO DOIS NOVOS REGISTROS INSERT INTO #TbIdentity (NoCliente, DaCadastro) VALUES ('Nome5',GETDATE ()) ,('Nome6',GETDATE())

Nesse ponto, teremos a seguinte situao na entidade temporria, conforme figura 4.


IdCliente 1 2 5 6 NoCliente Nome1 Nome2 Nome5 Nome6 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23

-- POPULANDO A ENTIDADE #TbIdentity COM 4 REGISTROS INSERT INTO #TbIdentity (NoCliente, DaCadastro) VALUES ('Nome1',GETDATE ()) ,('Nome2',GETDATE()) , ('Nome3',GETDATE()) , ('Nome4',GETDATE()) -- RECUPERANDO AS INFORMAES DA ENTIDADE #TbIdentity SELECT * FROM #TbIdentity

Figura 4. Entidade temporria com valores identidade fora de seqncia.

Vamos agora, inserir valores para que possamos preencher o intervalo entre o segundo e o terceiro registro. Mas, para isso, teremos que definir a propriedade SET IDENTITY_INSERT para ON. Essa propriedade, permite que seja inserido explicitamente valores em uma coluna definida com a propriedade IDENTITY, ou seja, auto incremento. Vale lembrar que somente uma tabela em uma sesso poder ter a propriedade IDENTITY_INSERT definida como ON. Isso quer dizer que, se uma entidade estiver com a propriedade definida como ON e uma instruo SET IDENTITY_INSERT ON for emitida para outra entidade, o SQL Server retornar uma mensagem de erro informando que SET IDENTITY_INSERT j est definido como ON.

Codificando.net e-magazine

Nesse momento, teremos a seguinte situao na entidade temporria, conforme figura 3.


IdCliente 1 2 3 4 NoCliente Nome1 Nome2 Nome3 Nome4 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Figura 3. Entidade temporria com coluna auto incremento.

Agora, vamos excluir os dois ltimos

www.codificando.net

Dez / Jan - 2010

24

Utilizando a propriedade Identity_Insert e DBCC CHECKIDENT

e-magazine

-- DEFININDO A PROPRIEDADE IDENTITY_INSERT PARA ON SET IDENTITY_INSERT #TbIdentity ON O valor default desta propriedade OFF, e preciso especficar o nome da tabela na qual ir receber o valor da propriedade. -- INSERINDO NOVOS REGISTROS INSERT INTO #TbIdentity (IdCliente ,NoCliente, DaCadastro) VALUES (3,'Nome5',GETDATE()) ,(4,'Nome6',GETDATE ())

-- INSERINDO NOVOS REGISTROS AINDA COM A PROPRIEDADE DEFINIDA PARA ON INSERT INTO #TbIdentity (IdCliente ,NoCliente, DaCadastro) VALUES (10,'Nome10',GETDATE())

Com isso, teremos a seguinte situao demonstrada na figura 6.


IdCliente 1 2 3 4 5 6 10 NoCliente Nome1 Nome2 Nome3 Nome4 Nome5 Nome6 Nome10 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Observe que, depois de definida a propriedade para ON, ser preciso explicitar o nome da coluna e os valores no comando INSERT, como mostra o exemplo T-SQL anterior. Agora, poderemos observar que o intervalo que tnhamos na entidade # TbIdentity entre o segundo e o terceiro registro, foi preenchido corretamente, conforme mostra a figura 5.
IdCliente 1 2 3 4 5 6 NoCliente Nome1 Nome2 Nome3 Nome4 Nome5 Nome6 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Figura 6. Entidade temporria com valor identidade inserido manualmente.

Agora, vamos definir a propriedade IDENTITY_INSERT para OFF.


-- DEFININDO A PROPRIEDADE IDENTITY_INSERT PARA OFF SET IDENTITY_INSERT #TbIdentity OFF -- INSERINDO UM NOVO REGISTRO INSERT INTO #TbIdentity (NoCliente, DaCadastro) VALUES ('Nome11',GETDATE())

Codificando.net e-magazine

Figura 5. Entidade temporria com valores identidade seqenciados corretamente.

Uma observao importante que se for explcito um valor maior que o valor de identidade atual na entidade, o SQL Server usar esse novo valor como o valor de identitade atual, ou seja, se for explcito o valor 10 no comando INSERT e, se voc modificar o valor da propriedade IDENTITY_INSERT de ON para OFF e inserir um novo valor, o valor da coluna identidade receber o valor 11, conforme demonstrado no cdigo abaixo.

Depois de executado esse comando TSQL, teremos a seguinte situao, demonstrada na figura 7, comprovando a teoria explicada anteriormente.
IdCliente 1 2 3 4 5 6 10 11 NoCliente Nome1 Nome2 Nome3 Nome4 Nome5 Nome6 Nome10 Nome11 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Figura 7. Entidade temporria com valor identidade inserido automaticamente.

www.codificando.net

Dez / Jan - 2010

25

Utilizando a propriedade Identity_Insert e DBCC CHECKIDENT

e-magazine

Outra forma de reorganizarmos a identidade de uma entidade especfica, utilizando a propriedade CHECKIDENT do comando DBCC, podendo ser definido um novo valor manualmente para uma coluna identidade de uma entidade. Digamos que, tenhamos uma entidade com uma coluna definida com o valor identidade. Inserimos 4 registros nela e teremos a seguinte populao na entidade, conforme demonstrado na figura 8.
IdCliente 1 2 3 4 NoCliente Nome1 Nome2 Nome3 Nome4 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23

identidade da coluna da entidade com a propriedade CHECKIDENT.


-- VERIFICANDO A IDENTITIDADE DA COLUNA IDENTITADE DBCC CHECKIDENT('#TbIdentity', NORESEED) Checking identity information: current identity value '4', current column value '4'. DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Figura 8. Entidade temporria com a coluna auto incremento.

Agora, se excluirmos os dois ltimos registros e inserirmos dois novos registros, teramos a seguinte populao na entidade, conforme demonstra a figura 9.
IdCliente 1 2 5 6 NoCliente Nome1 Nome2 Nome5 Nome6 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Ao executar o T-SQL acima, o SQL Server retornar uma mensagem nos mostrando o valor atual da identidade como quatro e o valor corrente tambm como quatro. Observe que, quem responsvel por mostrar o valor da identidade sem ser modificado o argumento NORESEED, que especificado juntamente com a propriedade CHECKIDENT. Para reorganizarmos esses valores sem correr o risco de ser criado, intervalos entre os registros na entidade, deveremos especificar o argumento RESEED, acompanhado de um valor que ser substitudo pelo valor da identidade atual. Veremos, no exemplo a seguir:
-- DEFININDO O VALOR DA IDENTITADE DA COLUNA IDENTITADE DBCC CHECKIDENT('#TbIdentity', RESEED, 2)
Checking identity information: current identity value '4', current column value '2'. DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Codificando.net e-magazine

Figura 9. Entidade temporria com valores identidades fora de seqncia.

Agora observe que nossa entidade possui um intervalo do segundo registro para o terceiro, isso totalmente desagradvel para quem gosta de manter seus registros organizados na sua base de dados conforme falado anteriormente, e uma outra forma de corrigir esse tipo de problema alem da propriedade IDENTITY seria a utilizao da propriedade CHECKIDENT. O primeiro passo verificar o valor

Observe agora, que o valor identidade corrente passa a ser justamente o que foi informado na expresso T-SQL.

Agora, vamos inserir mais dois novos registros e observar o resultado do mesmo.

www.codificando.net

Dez / Jan - 2010

26

Utilizando a propriedade Identity_Insert e DBCC CHECKIDENT

e-magazine

-- INSERINDO DOIS NOVOS REGISTROS INSERT INTO #TbIdentity(NoCliente, DaCadastro) VALUES ('Nome3',GETDATE()) ,('Nome4',GETDATE())

Agora, teremos o seguinte resultado aps a insero dos valores na entidade #TbIdentity, conforme demonstrado na figura 10.
IdCliente 1 2 3 4 NoCliente Nome1 Nome2 Nome3 Nome4 DaCadastro 2009-09-23 2009-09-23 2009-09-23 2009-09-23

Figura 10. Entidade temporria com novos valores identidade.

Espero ter sido bem sucinto quanto ao uso da propriedade SET IDENTITY_INSERT e DBCC CHECKIDENT. A todos um bom estudo e at a prxima. Jos Heberton Vilela de Melo
MSN: heberton_melo@hotmail.com MCP | MCTS em SQL Server 2008 | Projetista de Dados Lder da Turma do 2 Ano de Banco de Dados da FAL Vice-Lder da DBA-RN Students Tech Club Microsof Grupo: www.dbarnacademic.ning.com

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan - 2010

27

e-magazine

O Paradigma FILLFACTOR

Por: Laerte Junior

Um grupo de cientistas colocou cinco macacos numa jaula. No centro dela colocaram uma escada e, sobre ela, um cacho de bananas. Quando um macaco subia a escada para apanhar as bananas, os cientistas lanavam um jato de gua fria nos que estavam no cho. Depois de certo tempo, quando um macaco ia subir a escada, os outros o enchiam de pancada. Passado mais algum tempo, mais nenhum macaco subia a escada, apesar da tentao das bananas. Ento, os cientistas substituram um dos cinco macacos. A primeira coisa que ele fez foi subir a escada e foi rapidamente retirado pelos outros, que lhe bateram. Depois de algumas surras, o novo integrante do grupo no subia mais a escada. Um segundo foi substitudo, e o mesmo ocorreu, tendo o primeiro substituto participado, com entusiasmo, na surra ao novato. Um terceiro foi trocado, e repetiuse o fato. Um quarto e, finalmente, o ltimo dos veteranos foi substitudo. Os cientistas ficaram, ento, com um grupo de cinco macacos que, mesmo nunca tendo tomado um banho frio, continuavam a bater naquele que tentasse chegar s bananas.

Moral da Histria Se fosse possvel perguntar a algum deles por que batiam em quem tentasse subir a escada, com certeza a resposta seria: "No sei, as coisas sempre foram assim por aqui" O Paradigma FillFactor Tive a oportunidade de participar em um projeto em que a empresa tinha um DBA Junior. Em determinada anlise que estvamos fazendo, uma anlise e reorganizao dos ndices com base na carga de cada um, surgiu o dilogo: - Essa tabela eu conheo muito Insert . Pode colocar um Fillfactor baixo! Por que?, perguntei eu. - Eu no sei, aprendi assim e todo mundo fala isso... O paradigma FillFactor I " A existncia do page split" Continuando a minha pergunta, questionei-o sobre Page Split e a resposta foi: "Ah, isso eu sei, fcil. quando o SQL SERVER fica parecendo pipoca pulando de um lado para outro para achar os dados."
Dez/ Jan - 2010

Codificando.net e-magazine
|

www.codificando.net

28

O Paradigma FILLFACTOR

e-magazine

De uma certa maneira ele no estava errado e eu, particularmente, adorei o "pulando feito pipoca". Mas, sinceramente, essa era uma resposta que eu preferia no ter ouvido. Imagine se fosse algum do Storage Team... O que Page Split? Ns sabemos que o SQL SERVER trabalha com pginas de 8kb e cada pgina possui um fator de preenchimento, chamado fillfactor. Por default este fator 0, ou seja, pgina totalmente preenchida e sem espao livre para novos registros. Quando um registro inserido ou atualizado, este registro tem que ser armazenado no espao da pgina. Se a pgina no possui espao livre, o SQL Server precisa reorganizar todas as pginas para armazenar o novo registro. Mas estas novas pginas no so contnuas.

A verdade com 100% de FillFactor


Simplificando: John, Robert, Phil, Luca, Lucy, Chloe, Hannah and Julia decidiram ir praia. John era o organizador e resolveu colocar homens em um carro e mulheres em outro. Um dia antes da viagem, Luca resolveu no ir e Richard foi convidado. O layout ficou parecido com a figura 1 :

Figura 1 Layout sem espao no carro.

O FillFactor aplicado em um ndice quando este criado ou reorganizado e informa o quanto cada pgina do nvel folha ser preenchida. Page Split um processo interno que o Engine usa para acomodar os dados novos (ou quando mudamos o tamanho da informao em um campo varchar, por exemplo). Este processo consome uma carga considervel de I/O, tendo em vista que o Engine tem que ler a IAM (Index allocation Map), alocar novas pginas, mover os dados na ordem correta do ndice etc. O FillFactor mais efetivo no ndice cluster, mas pode ser aplicado nos ndices no cluster. O Paradigma FillFactor II "A verdade est l dentro"

No ltimo minuto, Luca decidiu ir, mas no havia espao no carro e, como a ordem era carro dos homens primeiro e mulheres depois, ele teve que ir com o seu. Se John quisesse falar com Luca, ele tinha que pular o carro das garotas e, o pior, se ele quisesse falar com Lucy , ele tinha que pedir pro Luca, pois ele era o nico a ter o nmero do celular dela. Se isto custoso para John, imagine pro Engine do SQL Server.... Na verdade, aqui temos um Page Split "praiano." Vamos ver o que acontece:

Codificando.net e-magazine
|

www.codificando.net

Dez/ Jan - 2010

29

O Paradigma FILLFACTOR

e-magazine

Este script nos gera um page split e o resultado da figura 3 :

Figura 2 Layout com a mala do Luca.

if object_id('Testfillfactor') is not null drop table Testfillfactor go create table Testfillfactor ( id int not null, name char(2000) ) create unique clustered index PK_TestFill on Testfillfactor (id) WITH( = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] go set nocount on declare @loop int set @loop = 1 while @loop < 11 begin insert into TestFillfactor values (@loop,'Name ' + convert(char(10),@loop)) set @loop = @loop + 2 end go dbcc ind(dba, Testfillfactor, 1, 0) go alter index PK_TestFill on Testfillfactor Rebuild PAD_INDEX = OFF, FILLFACTOR = 100, STATISTICS_NORECOMPUTE

Figura 3 Representao do dbcc ind.

Como a gente pode ver :

Duas Pginas de Dados (Data Pages) - Coluna PageType = 1 que so as pginas 7412 e 7414 Uma Pgina de ndice (Index Page) Coluna Pagetype = 2 que a pgina 7426 Uma IAM Page - Coluna PageType = 10 que a pgina 7413 Nosso foco so as pginas de dados (Data Pages)

Codificando.net e-magazine

01. Pgina 7412


Prxima Pgina de dados (NextPageID) = 7414 Pgina de Dados Anterior (PrevPageID) = 0

www.codificando.net

Dez/ Jan - 2010

30

O Paradigma FILLFACTOR

e-magazine

02. Pgina 7414

Prxima Pgina de dados (NextPageID) = 0 Pgina de Dados Anterior (PrevPageID) = 7412 Como eu criei a tabela com um valor fixo (char 2000), dever caber na pgina 7412 quatro linhas, que devem ser o ID 1, 3, 5 e 7. Para verificar usamos conforme figura 4:
dbcc page( 0, 1, 7412, 3)
Figura 5 Script para visualizar informao da Figura 4

Correto. Na pgina 7412 ns temos os IDs 1, 3, 5 e 7 Na pgina 7414 ns temos somente uma linha que o ID 9, sobrando espao no pelo FillFactor, e sim porque no tivemos dados suficientes para preench -la. Usando o script (figura 5), podemos confirmar (figura 6):

Figura 4 Representao do dbcc page.

Como a coluna m_slotCnt me informa o nmero de linhas que esta pgina tem (4) e a coluna m_freeCnt o nmero de bytes livres na pgina, minha conta est correta. Podemos executar este script para visualizar esta afirmao (figura 5): create table #dbccpageresults ( ParentObject varchar(max), [Object] varchar (max), [Field] varchar (max), [Value] varchar(max) ) insert into #dbccpageresults exec ('dbcc page( 0, 1, 7412, 3 ) with tableresults') select * from #dbccpageresults where [field] = 'id' go drop table #dbccpageresults

Codificando.net e-magazine

Figura 6 Script visualizar informao da pgina 7414.

E representando (figura 7):

www.codificando.net

Dez/ Jan - 2010

31

O Paradigma FILLFACTOR

e-magazine

Como podemos ver, uma nova pgina de dados (Data Page) foi inserida e ns temos o Page Split. Isso me lembra o Haley Joel Osment no filme Sexto Sentido: "Eu Vejo Page Spliiiiiiiiitsssss!!!!" Perceba que pelas colunas NextPageID e PrevPageID, o Engine tem que ir da pgina 7412 para a 7427 e depois para a 7414 para completar o ciclo da informaes. Representando (figura 9):

Figura 7 Representao das pginas , prxima e anterior.

Agora vamos inserir mais 4 linhas pares (no script inserimos linhas mpares). Lembre-se de que o ndice cluster sobre o ID (figura 8). Insert into Testfillfactor values (2,'Name 2') go Insert into Testfillfactor values (4,'Name 4') go Insert into Testfillfactor values (6,'Name 6') go Insert into Testfillfactor values (8,'Name 8') go dbcc ind(dba, Testfillfactor, 1, 0) go

Figura 9 Representao Page Split.

Codificando.net e-magazine

Luca h muito tempo e sei que ele vai mudar de idia. Vou deixar um espao em cada carro, caso ele queira levar mais algum tambm". E isto aconteceu, no ltimo minuto Luca chegou. E trouxe sua amiga, Jana. Como John deixou um espao livre em cada carro, no houve problema em acomodar todo mundo, e todos curtiram o final de semana!
Figura 8 Representao do Page Split.

Uma coisa j vemos de cara: o nmero de

www.codificando.net

Dez/ Jan - 2010

32

O Paradigma FILLFACTOR

e-magazine

carros aumentou com o mesmo nmero de pessoas que iam (antes do Luca e Jana). Vamos usar o (script 1) para vermos o que acontece , mas alterando o FillFactor para 30%.

set nocount on declare @loop int set @loop = 1 while @loop < 11 begin insert into TestFillfactor values (@loop,'Name ' + convert(char (10),@loop)) set @loop = @loop + 2 end go dbcc ind(dba, Testfillfactor, 1, 0) go alter index PK_TestFill on Testfillfactor Rebuild

E o que a figura 11 nos diz, sem pensar muito?


Figura 10 - Representao da Viagem com espao nos carros.

if object_id ('Testfillfactor') is not null drop table Testfillfactor go create table Testfillfactor ( id int not null, name char(2000) ) create unique clustered index PK_TestFill on Testfillfactor (id) WITH( PAD_INDEX = OFF, FILLFACTOR = 30,
Figura 11 Representao Fillfactor 30%.

Codificando.net e-magazine

Uma pgina de dados foi criada, mas com o mesmo nmero de linhas com o FillFactor de 100%

Como podemos ver:


Trs Pginas de Dados (Data Pages) Coluna PageType = 1, que so as pginas 7430,7406 e 7408; Uma Pgina de ndice (Index Page)

STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] go

www.codificando.net

Dez/ Jan - 2010

33

O Paradigma FILLFACTOR

e-magazine

Coluna Pagetype = 2, que a pgina 7407; Uma IAM Page - Coluna PageType = 10, que a pgina 7431. Nosso foco so as pginas de dados (Data Pages) 01. Pgina 7430

Prxima Pgina de dados (NextPageID) = 7406 Pgina de Dados Anterior (PrevPageID) = 0

Figura 12 Representao Pgina FillFactor 30% .

02. Pgina 7406


Prxima Pgina de dados (NextPageID) = 7408 Pgina de Dados Anterior (PrevPageID) = 7430

Como a coluna m_slotCnt me informa o nmero de linhas que esta pgina tem (2) e a coluna m_freeCnt o nmero de bytes livres na pgina, minha conta novamente est correta. E outra, a pgina 7406, ter os IDs 5 e 7, e a pgina 7408 o ID 9. Podemos executar este visualizar esta afirmao: script para

03. Pgina 7408


Prxima Pgina de dados (NextPageID) = 0 Pgina de Dados Anterior (PrevPageID) = 7406

Com eu criei a coluna fixa (char 2000) devemos ter na pgina 7430 duas linhas , que seriam o ID 3 e 5. Lembre-se que o ndice cluster sobre o ID. Verifcando (figura 12):
dbcc page( 0, 1, 7430, 3)

dbcc traceon( 3604 ) go create table #dbccpageresults ( ParentObject varchar(max), [Object] varchar(max), [Field] varchar(max), [Value] varchar(max) ) insert into #dbccpageresults exec ('dbcc page( 0, 1, 7430, 3 ) with tableresults') go select 'PAGE 7430',* from #dbccpageresults where [field] = 'id' go truncate table #dbccpageresults go

Codificando.net e-magazine
|

www.codificando.net

Dez/ Jan - 2010

34

O Paradigma FILLFACTOR

e-magazine

insert into #dbccpageresults exec ('dbcc page( 0, 1, 7406, 3 ) with tableresults') go select 'PAGE 7406',* from #dbccpageresults where [field] = 'id' go truncate table #dbccpageresults go insert into #dbccpageresults exec ('dbcc page( 0, 1, 7408, 3 ) with tableresults') go select 'PAGE 7408', * from #dbccpageresults where [field] = 'id' go drop table #dbccpageresults

Figura 14 Representao das Pginas.

Novamente vamos inserir mais 4 linhas pares :


Insert into Testfillfactor (2,'Name 2') go Insert into Testfillfactor (4,'Name 4') go Insert into Testfillfactor (6,'Name 6') go Insert into Testfillfactor (8,'Name 8') values values values values

E vamos rodar o script novamente :


dbcc traceon( 3604 ) go create table #dbccpageresults ( ParentObject varchar(max), [Object] varchar(max), [Field] varchar(max), [Value] varchar(max) ) insert into #dbccpageresults exec ('dbcc page( 0, 1, 7430, 3 ) with tableresults') go select 'PAGE 7430',* from #dbccpageresults where [field] = 'id' go truncate table #dbccpageresults go insert into #dbccpageresults exec ('dbcc page( 0, 1, 7406, 3 ) with tableresults') go select 'PAGE 7406',* from #dbccpageresults where [field] = 'id'

Codificando.net e-magazine

Figura 13 Script para visualizar informaes das pginas.

Ou:

www.codificando.net

Dez/ Jan - 2010

35

O Paradigma FILLFACTOR

e-magazine

go truncate table #dbccpageresults go insert into #dbccpageresults exec ('dbcc page( 0, 1, 7408, 3 ) with tableresults') go select 'PAGE 7408', * from #dbccpageresults where [field] = 'id' go drop table #dbccpageresults

O resultado o mesmo! Vamos mais a fundo: dbcc page( 0, 1, 7430, 1 ) go dbcc page( 0, 1, 7406, 1 ) go dbcc page( 0, 1, 7408, 1 )

O resultado sera (figura 16) :

Figura 16 Script visualizar informao sem page splits.

Figura 18 Visualizao das Pginas.

As pginas esto contnuas, e o engine no precisa pular de uma pgina a outra para achar os dados. No temos Page Split!!Ser?
dbcc ind(dba, Testfillfactor, 1, 0)

E representando (figura 19):

Codificando.net e-magazine

Figura 19 Sem Page Splits.

"Eu no vejo Page Spliiiiiiitttsssss".

Figura 17 - Representao das Pginas.

www.codificando.net

Dez/ Jan - 2010

36

O Paradigma FILLFACTOR

e-magazine

Qual a mgica?
No tem mgica. matemtica pura. Temos espao em cada pgina para acomodar os dados novos! O Paradigma FillFactor III - ndice Cluster+Identity = 100% FillFactor sem Page Splits? comum encontrarmos em fruns a seguinte pergunta (ou parecida com ela): "tenho um CIX (clustered index) no campo identity. Posso deixar com FillFactor de 100%?". E a resposta tradicional: "Sim. J que os dados so inseridos no final da pgina, no haver page splits". A resposta DEPENDE. correta na verdade

name5 varchar(1000), name6 varchar(1000), name7 varchar(1000), name8 varchar(1000), ) create unique clustered index PK_TestFill on Testfillfactor(id) WITH( OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] go set nocount on declare @loop int set @loop = 1 PAD_INDEX = OFF, FILLFACTOR = 100, STATISTICS_NORECOMPUTE =

Depende dos tipos de colunas que tero sua tabela e, principalmente, se elas tero atualizaes no tamanho do seu contedo (varchar, nvarchar, varbinary). Page Split ocorre no update tambm. Vamos l?
if object_id('Testfillfactor') is not null drop table Testfillfactor go create table Testfillfactor ( id int identity(1,1) not null, name1 varchar(1000), name2 varchar(1000), name3 varchar(1000), name4 varchar(1000),

while @loop < 50 begin insert into TestFillfactor (name1,name2,name3,name4,name5 ,name6,name7,name8) values ('Name 1 ' + convert(char(10),@loop),'Name 2 ' + convert(char (10),@loop),'Name 3 ' + convert(char(10),@loop), 'Name 4 ' + convert(char (10),@loop),'Name 5 ' + convert(char(10),@loop),'Name 6 ' + convert(char (10),@loop),'Name 7 ' + convert(char(10),@loop), 'Name 8 ' + convert(char (10),@loop)) set @loop = @loop + 1 end go Criamos uma tabela com tipos de dados variante. Reparem que os campos nome so varchar. Populamos com 50 linhas contnuas (identity , com CIX no campo ID). Teoricamente no haveria Pages Splits. Ser?

Codificando.net e-magazine
|

www.codificando.net

Dez/ Jan - 2010

37

O Paradigma FILLFACTOR

e-magazine

alter index PK_TestFill on Testfillfactor Rebuild go dbcc ind(dba, Testfillfactor, 1, 0) go

Figura 21 Representao de page splits no update .

Uma CIVILIZAO DE PAGE SPLITS!


Fig 20 Sem page Splits na Insero.

Certeza, Laerte? Apesar de o campo NextPageId j me mostrar isso, mas vamos ver: Peguei a Pgina 7548. O prximo deveria ser a Pgina 7549. create table #dbccpageresults ( ParentObject varchar (max), [Object] varchar(max), [Field] varchar(max),

Correto. No vemos "Page SPLIIIIIIIIITTSSS". MAS, vamos alterar o contedo dos campos nome? update Testfillfactor set name1 = REPLICATE('X',1000), name2 = REPLICATE('X',1000), name3 = REPLICATE('X',1000), name4 = REPLICATE('X',1000), name5 = REPLICATE('X',1000), name6 = REPLICATE('X',1000), name7 = REPLICATE('X',1000), name8 = REPLICATE('X',1000) go dbcc ind(dba, Testfillfactor, 1, 0)

Codificando.net e-magazine

[Value] varchar(max) ) insert into #dbccpageresults exec ('dbcc page( 0, 1, 7548, 3 ) with tableresults') select * from #dbccpageresults where [field] = 'id' go truncate table #dbccpageresults go insert into #dbccpageresults exec ('dbcc page( 0, 1, 7549, 3 ) with tableresults') go

Vendo como ficou:

www.codificando.net

Dez/ Jan - 2010

38

O Paradigma FILLFACTOR

e-magazine

select * from #dbccpageresults where [field] = 'id' go drop table #dbccpageresults

select * from #dbccpageresults where [field] = 'id' go drop table #dbccpageresults

Figura 23 Visualizao das Pginas. Figura 22 Visualizao das Pginas.

Errado! Segundo o NextPageID, a Prxima Pgina a 8174, que est l embaixo e nem aparece na imagem por no caber! Pegando as pginas 7548 e 8174: create table #dbccpageresults ( ParentObject varchar (max), [Object] varchar(max), [Field] varchar(max), [Value] varchar(max)) insert into #dbccpageresults exec ('dbcc page( 0, 1, 7548, 3 ) with tableresults') select * from #dbccpageresults where [field] = 'id' go truncate table #dbccpageresults go insert into #dbccpageresults exec ('dbcc page( 0, 1, 8174, 3 ) with tableresults') go

Agora sim! Ou seja da pgina 7548 pulou para a pgina 8174 para continuar a ordem do CIX (clustered index)! Ou seja, a afirmao que s basta colocar o CIX no identity e pode deixar o FillFactor com 100% que no ter Page Splits LENDA. Alm do que, fazendo isso, se sua tabela tiver uma carga alta de inserts, voc poder criar um hotspot (muita insero ao mesmo tempo).

Codificando.net e-magazine
|

Se sua tabela tem campos de tamanho varivel (varchar, nvarchar, varbinary) e estes so altamente atualizados (seja com valores maiores ou menores) provavelmente voc ter Page Split. Se sua tabela tem campos de tamanho varivel (varchar, nvarchar, varbinary) e estes NO so atualizados ou no tem, a colocao do CIX no identity e FillFactor de 100% parece ser mais vivel.

O Paradigma FillFactor IV - Muito cuidado!

www.codificando.net

Dez/ Jan - 2010

39

O Paradigma FILLFACTOR

e-magazine

Espera, deixa eu ver se entendi. NESTE CASO: Com FillFactor de 100% o Engine acomoda 4 linhas na pgina. Eu tenho um menor nmero de pginas e Page Split. Com FillFactor de 30% o Engine acomoda 2 linhas na pgina. Eu tenho um nmero maior de pginas, mas no tenho Page Split. Mas um nmero maior de pginas no quer dizer mais Logical Reads? CORRETO! Vamos ver se verdade? Primeiro, com 30% de FillFactor:
if object_id('Testfillfactor') is not null drop table Testfillfactor go create table Testfillfactor ( id int not null, name char(2000) ) create unique clustered index PK_TestFill on Testfillfactor(id) WITH( OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] Go go alter index PK_TestFill on Testfillfactor Rebuild go set nocount on declare @loop int set @loop = 1 while @loop < 10000 begin PAD_INDEX = OFF, FILLFACTOR = 30, STATISTICS_NORECOMPUTE =

insert into TestFillfactor values (@loop,'Name ' + convert (char(10),@loop)) set @loop = @loop + 1 end go set statistics io on go select ID from TestFillfactor where id = 9999 go set statistics io off Table 'Testfillfactor'. Scan count 1, logical reads 55, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Agora, com 100% de FillFactor:


if object_id('Testfillfactor') is not null drop table Testfillfactor go create table Testfillfactor ( id int not null, name char(2000) ) create unique clustered index PK_TestFill on Testfillfactor(id) WITH( OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] go alter index PK_TestFill on Testfillfactor Rebuild go set nocount on declare @loop int set @loop = 1 while @loop < 10000 begin insert into TestFillfactor values (@loop,'Name ' + convert (char(10),@loop)) set @loop = @loop + 1 end go PAD_INDEX = OFF, FILLFACTOR = 100, STATISTICS_NORECOMPUTE =

Codificando.net e-magazine
|

www.codificando.net

Dez/ Jan - 2010

40

O Paradigma FILLFACTOR

e-magazine

set statistics io on go select ID from TestFillfactor where id = 9999 go set statistics io off Table 'Testfillfactor'. Scan count 1, logical reads 30, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Identifique as consultas das tabelas envolvidas (DMVs e Profiler so uma boa ajuda) Converse com o pessoal de Negcios (analista de negcios) e entenda o "produto final" do uso destas consultas. Por exemplo, um relatrio de vendas online por filial Crie suas prprias mtricas de controle e organizao. Um baseline no serve somente para dados macros do servidor Se o seu problema um caso particular, crie um baseline para este processo. Como voc poder saber se melhorou ou ficou pior com seus ajustes se voc no sabe como era o comportamento dele antes, durante e depois? Entenda o Produto (SQL Server) Nada melhor que voc entender um pouco como funciona internamente o que est acontecendo. Isto lhe dar uma viso clara e objetiva para definir sua soluo.

verdade! Baixo FillFactor --> Alto Page Reads Alto FillFactor --> Baixo Page Reads Se formos pela lgica: Muito Insert, update = Baixo FillFactor Muito Select = Alto FillFactor Mas sabemos que n prtica no existe regra. Cada ambiente diferente do outro e possui caractersticas prprias, seja pela regra de negcio envolvida, seja por limitao de infra (falta de janela de reindexao) ou alta disponibilidade. Algumas vezes interessante deixar um alto Fillfactor para uma tabela de muito insert e update, mas tambm esta tabela tem muito select, pois alimenta um relatrio muito importante pra sua organizao e chamada muitas vezes ao dia... Neste caso, reindexar ONLINE (ou reorganizar) mais vezes este ndice pode ser mais vantajoso. Eu tenho certeza disso? Claro que no. Mas eu fao algumas coisas que me ajudam na anlise e definio da soluo: Analise a carga de seus ndices separadamente (cada um deles tem uma caraterstica diferente)

Codificando.net e-magazine

Exemplo de timas leituras: Inside Microsoft SQL Server 2005: T-SQL Querying Inside Microsoft SQL Server 2005: The Storage Engine Inside Microsoft SQL Server 2005: Query Tuning and Optimization E os mesmos livros no SQL SERVER 2008 No tenha medo de dizer "eu no sei, mas vou ver e aprender". Isso muito melhor do que dizer "eu no sei... sempre foi assim... aprendi assim". Na verdade voc esta

www.codificando.net

Dez/ Jan - 2010

41

O Paradigma FILLFACTOR

e-magazine

dizendo "eu no sei, no quero saber e no tenho a mnima vontade de aprender" e isso no soa bem. Quando tiver todo controle da situao: teste. Teste muito. Canse de testar antes de dizer "o jeito de fazer assim". As pessoas esperam isso de voc. A deciso correta "faa assim. Eu sei o que estou falando!".

Concluso Vimos que o FillFactor pode ser o heri ou vilo da histria. Teste, implemente com cuidado. Trate cada objeto e entidade do seu banco de dados como nica e sendo assim o comportamento diferente uma das outras. E no olhe para Paradigmas. Especialmente em TI. At a prxima! Laerte Junior
Certificado MCDBA com mais de 8 anos de atuao com SQL SERVER, fascinado por cdigos e scripts, escreve artigos para MCDBABrasil, Imasters e Simple-Talk aonde possue um blog tambm. Coloca suas experincias com SQL SERVER e Powershell no www.laertejuniordba.spaces.live.com Developer do projeto CODEPLEX SQLPSX - SQL Server Powershell Extensions http://sqlpsx.codeplex.com/ Laerte Junior $hell Your Experience www.laertejuniordba.spaces.live.com www.simple-talk.com/community/blogs/laerte/ www.twitter.com/laertejuniordba SQL Server Powershell Extensions Developer

Codificando.net e-magazine
|

www.codificando.net

Dez/ Jan - 2010

42

e-magazine

Explorando microsot sql reporting services 2005


Por: Caio Azevedo

Ol pessoal, nessa edio vrios exemplos dos relatrios Local Mode, lembrando que todos os cdigos aqui implementados esto disponveis no site da nossa comunidade, http:// comunidade.codificando.net/, bom divertimento. Parte 3 local mode - demos Exemplos de relatrios A seguir criaremos alguns relatrios para exemplificar o que j vimos at ento, bem como alguns recursos que veremos com os relatrios que criaremos. Nossos exemplos so baseados no modelo de dados apresentado na parte dois do nosso artigo que relaciona pedidos, itens de pedido, produtos e vendedores. Relatrio tabular Nesse exemplo criaremos um relatrio que nos permite visualizar a relao de produtos, suas respectivas categorias, total em estoque e valor unitrio. O usurio desse relatrio pode selecionar uma ou mais categorias de produtos que deseja visualizar. O relatrio faz uso de formatao condicional para destacar as quantidades em estoque se esse for inferior a 250, tambm faremos uso dos recursos de formatao de moeda e ordenao da coluna: Nome do

Produto. Criando o Relatrio Esse relatrio exibe as colunas com o nome, categoria, total em estoque e valor unitrio de cada produto. Primeiro Passo: Construo do DataSet Adicionar um objeto dataSet com o nome Tabular (vide sesso Repositrio de dados Local - DataSet) aplicao na pasta DataSources, e adicionar a ele um datatable com a estrutura da figura 1.

Codificando.net e-magazine

Figura 1 Datatable Produtos Estoque.

Esse datatable ser preenchido com os dados provenientes do resultado da seguinte stored procedure: getProdutosinCategorias, que recebe como parametro uma string com as identificaes das categorias separadas por vrgula. Segundo Passo: Criao e modelagem do Relatrio Incluiremos um novo relatrio em nosso

www.codificando.net

Dez / Jan - 2010

43

Explorando microsot sql reporting services 2005

e-magazine

projeto chamado TBProdutosporCategoria, na pasta Reports (vide artigos anteriores). Usando um objeto Table da toolbox dos relatrios, criaremos a estrutura do relatrio formatado conforme a figura 2 .

Figura 3 ordenao colunas.

Figura 2 relatrio tabular.

Criando o Cliente
Para configurao do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida adicionamos o cdigo cliente para carga do dataTable e configurao do reportViewer criado. A seguir apresentamos um trecho do cdigo para carga da datatable e configurao do reportViewer com destaque para passagem dos parmetros na stored procedure utilizada para carga do datatable, idscategoria.

Terceiro Passo: Formatar o relatrio


Destacaremos os itens da coluna de estoque com valor inferior a 250, para tal selecionamos a janela de propriedades da caixa de texto e no atributo Color selecionamos Expressions, ento criamos uma instruo da seguinte forma:
=IIf(Fields! QT_ESTOQUE.Value<250,"Red","Blue")

Codificando.net e-magazine

Em seguida, adicionamos as funcionalidades de ordenao nas colunas, para tal, basta configurar a caixa de texto Nome Produto, na tab Interative Sort, como na figura 3.

SqlParameter[] parms = { new SqlParameter ("@idCategorias", SqlDbType.VarChar,20) }; parms[0].Value = getIdCategorias (); //mtodo auxiliar que recupera as categorias da interface do usurio. cmdReport.CommandType = CommandType.StoredProcedure; cmdReport.Connection = conReport; foreach (SqlParameter parm in parms) cmdReport.Parameters.Add (parm); cmdReport.CommandText = "getProdutosinCategorias"; drReport = cmdReport.ExecuteReader ();

www.codificando.net

Dez / Jan - 2010

44

Explorando microsot sql reporting services 2005

e-magazine

dsReport.Tables[0].Load(drReport); drReport.Close(); conReport.Close(); rptViewTable.LocalReport.ReportPat h = "Reports// TBProdutosporCategoria.rdlc"; ReportDataSource rds = new ReportDataSource(); rds.Name = "Tabular_ProdutosEstoque"; rds.Value = dsReport.Tables[0]; rptViewTable.LocalReport.DataSourc es.Clear(); rptViewTable.LocalReport.DataSourc es.Add(rds); this.rptViewTable.RefreshReport();

pedido, e vendida.

sua

respectiva

quantidade

Primeiro Passo: Construo do DataSet


Adicionar um objeto dataSet com o nome MasterDetail (vide sesso Repositrio de dados Local - DataSet) aplicao na pasta DataSources, e adicionar a ele um datatable com a estrutura da figura 5.

Finalmente eis nosso relatrio em ao:

Figura 5 datatable Itens do Pedido.

Esse datatable ser preenchido com os dados provenientes do resultado da seguinte instruo SQL:
SELECT [ITE].ID_PEDIDO, [PRO].DS_PRODUTO, [ITE].QT_PRODUTO FROM TB_ITENS_PEDIDO [ITE] INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO

Figura 4 relatrio em ao.

Relatrio master-detail
Nesse exemplo criaremos um relatrio que nos permite visualizar pedidos e seus respectivos itens. Para criao do masterdetail, faremos uso da funcionalidade de subreports com parmetros para relacionar o relatrio principal (lista de pedidos) e seus respectivos itens. Criando o relatrio Detail Comearemos com a construo do relatrio que ser o detail da nossa implementao. Esse relatrio exibe duas colunas com a descrio do produto do

Segundo Passo: Criao e modelagem do Relatrio


Incluiremos um novo relatrio em nosso projeto chamado MDItensPedido na pasta Reports. Usando um objeto Table da toolbox dos relatrios, criaremos a estrutura do relatrio formatado conforme a figura abaixo.

Codificando.net e-magazine

Figura 6 relatrio detail.

www.codificando.net

Dez / Jan - 2010

45

Explorando microsot sql reporting services 2005 Terceiro Passo: Criar o parmetro para associar ao Master
Aqui criaremos o parmetro, (vide sesso Parametrizao), que ser o link com o relatrio Master, esse parmetro chamaremos de idPedido do tipo Integer e Hidden.
Figura 8 DataTable do Pedido.

e-magazine

Adicionar um datatable ao nosso Dataset com a estrutura da figura 8.

Quarto Passo: Criar um filtro Atravs das propriedades da tabela criada no segundo passo, criaremos um filtro dos dados do relatrio, onde a identificao do pedido ser aquela correspondente ao parmetro criado no terceiro passo. A figura 7 ilustra a operao. Esse datatable ser preenchido com os dados provenientes do resultado da seguinte instruo SQL:
SELECT [ped].ID_PEDIDO, [VEN].NO_VENDEDOR, CONVERT (SMALLDATETIME, [PED].DT_PEDIDO, 103) as DT_PEDIDO, SUM ([ITE].QT_PRODUTO*[PRO].VL_PRECO) as [Valor do Pedido] FROM TB_PEDIDO [PED] INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR GROUP BY [ped].ID_pedido,[VEN].NO_VENDEDOR, [PED].DT_PEDIDO

Segundo Passo: Criao e modelagem do Relatrio


Figura 7 configurando filtro.

Codificando.net e-magazine

Criando o relatrio Master


Na criao do relatrio master, exibimos a identificao do pedido, o nome do vendedor, a data do pedido e o valor em reais da venda do pedido. O grande diferencial desse relatrio a incluso do item Subreport como se fosse uma coluna de uma table e configurar o subreport para associar o campo de identificao do pedido ao seu parmetro.

Incluiremos um novo relatrio em nosso projeto chamado MDPedido, na pasta Reports. Usando um objeto Table da toolbox dos relatrios criaremos a estrutura do relatrio formatado conforme a figura 9:

Primeiro Passo: Construo do Datatable no DataSet

Figura 9 relatrio master.

www.codificando.net

Dez / Jan - 2010

46

Explorando microsot sql reporting services 2005

e-magazine

Terceiro Passo: Configurar o subreport


Aqui configuraremos o item subreport de modo a estabelecer o vnculo entre o relatrio master e o detail atravs do parmetro, idPedido, criado no relatrio Detail, essa configurao feita nas propriedades do subreport , tab Parameters, como ilustra a figura 10:

Figura 10 parmetros do subReport.

Criando o Cliente
Para configurao do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida adicionamos o cdigo cliente para carga dos dataTables e configurao do reportViewer criado. A seguir apresentamos um trecho do cdigo para carga das duas datatables e configurao do reportViewer. A primeira instruo (em vermelho) carrega a tabela Pedido e a segunda a ItensPedido. Vemos tambm que s configuramos o datasource do relatrio master, e o relatrio detail ? A seguir:
cmdReport.CommandType = CommandType.Text; cmdReport.Connection = conReport; cmdReport.CommandText = "SELECT [ped].ID_PEDIDO,

[VEN].NO_VENDEDOR, CONVERT (SMALLDATETIME, [PED].DT_PEDIDO, 103) as DT_PEDIDO, SUM ([ITE].QT_PRODUTO*[PRO].VL_PRECO) as [Valor do Pedido] FROM TB_PEDIDO [PED] INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR GROUP BY [ped].ID_pedido,[VEN].NO_VENDEDOR, [PED].DT_PEDIDO ; SELECT [ITE].ID_PEDIDO, [PRO].DS_PRODUTO, [ITE].QT_PRODUTO FROM TB_ITENS_PEDIDO [ITE] INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO"; drReport = cmdReport.ExecuteReader (); dsReport.Load (drReport,LoadOption.OverwriteChang es,dsReport.Tables [0],dsReport.Tables[1]); drReport.Close(); conReport.Close(); rptViewMasterDetail.LocalReport.Rep ortPath = "..//..//Reports// MDPedido.rdlc"; ReportDataSource rds = new ReportDataSource(); rds.Name = "MasterDetail_Pedido"; rds.Value = dsReport.Tables[0]; rptViewMasterDetail.LocalReport.Dat aSources.Clear(); rptViewMasterDetail.LocalReport.Dat aSources.Add(rds); rptViewMasterDetail.RefreshReport (); Os dados do relatrio detail so carregados com a tabela ItensPedido do dataSet, e so configurados no evento de processamento do subReport que acessvel atravs do delegate SubreportProcessingEventHandler que assinado no construtor da classe da aplicao com a seguinte instruo: rptViewMasterDetail.LocalReport.Sub reportProcessing += new SubreportProcessingEventHandler (SubReportDetailProcessing); Em seguida implementamos o mtodo SubReportDetailProcessing com as seguintes instrues:

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan - 2010

47

Explorando microsot sql reporting services 2005


private void SubReportDetailProcessing(object sender, SubreportProcessingEventArgs e) { e.DataSources.Add(new ReportDataSource ("MasterDetail_ItensPedido", dsReport.Tables[1])); }

e-magazine

dados Local - DataSet) aplicao na pasta DataSources, e adicionar ele um datatable com a estrutura da figura 12.

Finalmente eis nosso relatrio em ao:

Figura 12 DataTable Vendas.

Esse datatable ser preenchido com os dados provenientes do resultado da seguinte instruo SQL:
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 [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR WHERE CONVERT (SMALLDATETIME, [PED].DT_PEDIDO, 103) BETWEEN '99/99/9999' AND '99/99/9999' GROUP BY [VEN].NO_VENDEDOR

Figura 11 relatrio master-detail.

Relatrio grfico Nesse exemplo criaremos um relatrio que nos permite visualizar graficamente as vendas, em reais, dos nossos vendedores por perodo. Nesse relatrio faremos uso da funcionalidade Chart da toolbox dos relatrios, o perodo das vendas a serem consultadas ser passado como parmetro para instruo SQL que far a busca no banco de dados, o que uma alternativa mais prudente que o uso de filtros no relatrio j que no necessitamos recuperar todos os registros das vendas. Criando o relatrio Esse relatrio correlaciona duas informaes para gerar nosso grfico, Nome do vendedor e o total de sua venda. Primeiro Passo: Construo do DataSet. Adicionar um objeto dataSet com o nome Grafico (vide sesso Repositrio de

Segundo Passo: Criao e modelagem do Relatrio Incluiremos um novo relatrio em nosso projeto chamado GrVendas, na pasta Reports. Usando um objeto Chart da toolbox dos relatrios, criaremos a estrutura do relatrio formatado conforme a figura 13:

Codificando.net e-magazine

Figura 13 formatando relatrio chart.

www.codificando.net

Dez / Jan - 2010

48

Explorando microsot sql reporting services 2005

e-magazine

Terceiro Passo: Configurar o relatrio Aqui configuraremos o item Chart de modo a torn-lo parecido ao exibido na imagem 13. Quarto Passo: Criar os parmetros do perodo Nosso relatrio tambm exibe o perodo da consulta que exibido na sesso header do relatrio. Para recuperar essas informaes fornecidas pelo cliente recorremos aos parmetros, dtInicio e dtFim, esta configurao feita nas propriedade do relatrio , tab Parameters. Criando o Cliente Para configurao do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida adicionamos o cdigo cliente para carga do dataTable e configurao do reportViewer criado. A seguir apresentamos um trecho do cdigo para carga da datatable e configurao do reportViewer com destaque para passagem dos parmetros 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 [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR WHERE CONVERT (SMALLDATETIME, [PED].DT_PEDIDO,

103) BETWEEN CONVERT (SMALLDATETIME,'" + txtDtInicio.Text + "',103) AND CONVERT(SMALLDATETIME,'" + txtDtFim.Text + "',103) GROUP BY [VEN].NO_VENDEDOR"; drReport = cmdReport.ExecuteReader (); dsReport.Tables[0].Load(drReport); drReport.Close(); conReport.Close(); rptViewGrafico.LocalReport.ReportPa th = "..//..//Reports// GrVendas.rdlc"; ReportParameter[] parPeriodo = { new ReportParameter ("dtInicio",txtDtInicio.Text), new ReportParameter ("dtFim",txtDtFim.Text)}; rptViewGrafico.LocalReport.SetParam eters(parPeriodo); ReportDataSource rds = new ReportDataSource(); rds.Name = "Grafico_Vendas"; rds.Value = dsReport.Tables[0]; rptViewGrafico.LocalReport.DataSour ces.Clear(); rptViewGrafico.LocalReport.DataSour ces.Add(rds); rptViewGrafico.RefreshReport();

Finalmente eis nosso relatrio em ao:

Codificando.net e-magazine

Figura 14 relatrio chart em ao

Relatrio document map Nesse exemplo criaremos um relatrio que nos permite visualizar pedidos, seus

www.codificando.net

Dez / Jan - 2010

49

Explorando microsot sql reporting services 2005

e-magazine

respectivos itens e o valor total do pedido dentro de um perodo informado pelo usurio. Utilizaremos um recurso chamado DocumentMap, onde listamos os vendedores e seus respectivos pedidos com recurso de um link para os detalhes do vendedor ou do pedido. Criando o relatrio Esse relatrio lista os vendedores, seus pedidos e detalhes do pedido, com recurso de navegao via Document Map. Primeiro Passo: Construo do DataSet Adicionar um objeto dataSet com o nome DocumentMap (vide sesso Repositrio de dados Local - DataSet) aplicao na pasta DataSources, e adicionar ele um datatable com a estrutura da figura 15.

[VEN].ID_VENDEDOR INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO= ITE.ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON ITE.ID_PRODUTO = PRO.ID_PRODUTO

Segundo Passo: Criao e modelagem do Relatrio Incluiremos um novo relatrio em nosso projeto chamado DMapPedido, na pasta Reports. Usando um objeto Table da toolbox dos relatrios criaremos a estrutura do relatrio formatado conforme a figura 16:

Figura 16 formatando relatrio Document Map.

Terceiro Passo: Configurar o relatrio Aqui configuraremos o item Table de modo a torn-lo parecido ao exibido na imagem acima. Para tal faremos uso de uma das propriedades mais poderosas das tabelas que a tab Groups. Essa propriedade nos permite, como o nome diz, agrupar os registros por um ou mais campos, similar clusula GROUP BY do T-SQL. Na figura 16 percebe-se que fizemos dois agrupamentos, 1 e 2, respectivamente pelos campos NO_VENDEDOR e ID_PEDIDO. Comeamos nossa configurao criando um relatrio com os atributos acima, configurando-o como um relatrio tabular,

Codificando.net e-magazine

Figura 15 datatable Peddo.

Esse datatable ser preenchido com os dados provenientes do resultado da seguinte instruo SQL:
SELECT [PED].ID_PEDIDO, [PED].ID_VENDEDOR, [VEN].NO_VENDEDOR, [PED].DT_PEDIDO ,[pro].DS_PRODUTO, [ite].QT_PRODUTO, [pro].VL_PRECO FROM TB_PEDIDO [PED] INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR =

www.codificando.net

Dez / Jan - 2010

50

Explorando microsot sql reporting services 2005

e-magazine

em seguida nas propriedades da tabela criamos os agrupamentos nomeados table1_grpVendedor e table1_grpPedido, necessariamente nessa ordem, conforme a imagem 17.

na rea de rodap do agrupamento de pedidos, com uma expresso que soma os valores individuais de cada produto multiplicado pela quantidade vendida, codificado da seguinte forma:
=Sum(Fields! QT_PRODUTO.Value*Fields! VL_PRECO.Value)

Finalmente, formatamos as caixas de texto com data e moeda, bem como as cores de fundo das linhas. Quarto Passo: Criar os parmetros do perodo Nosso relatrio tambm exibe o perodo da consulta que exibido na sesso header do relatrio. Para recuperar essas informaes fornecidas pelo cliente recorremos aos parmetros, dtInicio e dtFim, essa configurao feita nas propriedades do relatrio - tab Parameters. Criando o Cliente Para configurao do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida adicionamos o cdigo cliente para carga do DataTable e configurao do reportViewer criado. A seguir apresentamos um trecho do cdigo para carga da datatable e configurao do reportViewer com destaque para passagem dos parmetros dtInicio e dtFim.
cmdReport.CommandType = CommandType.Text; cmdReport.Connection = conReport; cmdReport.CommandText = "SELECT [PED].ID_PEDIDO, [PED].ID_VENDEDOR, [VEN].NO_VENDEDOR, [PED].DT_PEDIDO, [pro].DS_PRODUTO, [ite].QT_PRODUTO, [pro].VL_PRECO FROM TB_PEDIDO [PED] INNER JOIN TB_VENDEDOR [VEN] ON

Figura 17 criando grupos do relatrio Document Map.

Em seguida, na mesma caixa de edio do grupo, configuramos o recurso de Document Map, que corresponde a um dos recursos de navegao dos relatrios do Reporting Services. Essa configurao feita simplesmente especificando o Document Map Label de cada grupo. Para o primeiro grupo, utilizamos o campo correspondente ao nome do vendedor, no segundo sofisticamos com a criao de uma expresso que concatena uma string com o campo de identificao do pedido. Finalmente movemos os campos nome do vendedor e identificao do pedido para as linhas de cabealho dos seus respectivos grupos. Outro elemento interessante em nosso relatrio, e muito comum em relatrios com agrupamento, so totalizadores. No nosso relatrio, sumarizamos o total do pedido em uma caixa de texto posicionada

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan - 2010

51

Explorando microsot sql reporting services 2005

e-magazine

[PED].ID_VENDEDOR = [VEN].ID_VENDEDOR INNER JOIN TB_ITENS_PEDIDO[ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ; cmdReport.CommandText += " ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO WHERE CONVERT (SMALLDATETIME, [ped].DT_PEDIDO,103) BETWEEN CONVERT(SMALLDATETIME,'" + txtDMdtInicio.Text + "',103) AND CONVERT(SMALLDATETIME,'" + txtDMdtFim.Text + "',103)"; drReport = cmdReport.ExecuteReader (); dsReport.Tables[0].Load(drReport); drReport.Close(); conReport.Close(); rptViewGrafico.LocalReport.ReportP ath = "..//..//Reports// DMapPedido.rdlc"; ReportParameter[] parPeriodo = { new ReportParameter ("dtInicio",txtDMdtInicio.Text), new ReportParameter ("dtFim",txtDMdtFim.Text)}; rptViewGrafico.LocalReport.SetPara meters(parPeriodo); ReportDataSource rds = new ReportDataSource(); rds.Name = "DocumentMap_Pedido"; rds.Value = dsReport.Tables[0]; rptViewGrafico.LocalReport.DataSou rces.Clear(); rptViewGrafico.LocalReport.DataSou rces.Add(rds); rptViewGrafico.RefreshReport();

Os relatrios Local-mode so uma excelente alternativa para pequenas e mdias aplicaes onde os relatrios podem compartilhar recursos dos sistemas e no dispomos de uma infra-estrutura mais elaborada. Abaixo relacionamos alguns dos itens que apontamos como limitaes desse modelo de relatrios.

S exporta para os formatos Excel e PDF No suporta interface customizada No disponibiliza interface aos usurios para os parmetros Document map no suportado em FireFox Compartilha os recursos da aplicao cliente

isso ai pessoal, no prximo captulo uma verdadeira revoluo, os relatrios remote mode, simplesmente imperdvel, at l. Caio Azevedo
Graduado em Cincia da Computao, Engenharia Civil e louco por cincias exatas em especial fsica e matemtica. Coordenador da Clula Microsoft da Magna Sistema e Arquiteto Microsoft, palestrante, tecno-colunista e instrutor da treinando .net. MCP, MCAD, MCSD, MCTS e MCPD. E fantico pela srie Star Wars may the force be with you.

Codificando.net e-magazine

Finalmente eis nosso relatrio em ao:

Figura 18 relatrio Document Map em ao

Limitaes

www.codificando.net

Dez / Jan - 2010

52

e-magazine

Introduo ao Query Processor


Por: Fabiano Neves Amorim

Incio Escolher o melhor caminho para chegar a determinado lugar pode ser considerado para muitos uma arte, isso porque sempre existem vrios caminhos que levam ao mesmo destino. Executar uma tarefa da forma mais eficiente possvel requer que o caminho percorrido seja o melhor dentre as centenas de variveis que podem influenciar na escolha do melhor percurso. No SQL Server o responsvel por calcular a maneira mais eficiente de acesso aos dados chamado de Query Processor, ele dividido em duas partes, o Query Optimizer e o Query Execution Engine. Veremos neste artigo como o Query Optimizer funciona e quais os passos necessrios para execuo de um comando T-SQL. Entender como funciona e como interpretar o trabalho do Query Optimizer uma das melhores maneiras de aprimorar seus conhecimentos em SQL Server. Esse conhecimento ser de grande valor quando voc precisar fazer algum trabalho de tunning em banco de dados.

Ambiente Para melhor entendimento dos exemplos deste artigo criaremos uma tabela, com alguns dados e uma viso, que serviro como base para os testes que sero apresentados. A Listagem 1 contm o script para criao destes objetos. O Script cria a tabela Funcionarios com algumas informaes (ID, Nome, Salrio, Telefone e Cidade) e, em seguida, so inseridos alguns registros. Logo aps, uma view (vw_Funcionarios) criada. A grosso modo, podemos dizer que Views so tabelas virtuais definidas por uma consulta T-SQL. A nossa view, criada na Listagem 1, retorna o nome e o salrio de todos os funcionrios que ganham mais de R$ 900,00.
CREATE TABLE Funcionarios(ID Int IDENTITY(1,1) PRIMARY KEY, Nome VarChar(30), Salario Numeric(18,2), Telefone VarChar(15), Cidade VarChar(80)); INSERT INTO Funcionarios(Nome, Salario, Telefone, Cidade) VALUES('Jos', 850.30, '1155960015', 'So Paulo'); INSERT INTO Funcionarios(Nome, Salario, Telefone, Cidade) VALUES('Antonio', 950, '1181115544', 'So Paulo');

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan - 2010

53

Introduo ao Query Processor

e-magazine

INSERT INTO Funcionarios(Nome, Salario, Telefone, Cidade) VALUES('Joo', 1200, '1144123321', 'So Paulo'); CREATE VIEW vw_Funcionarios AS
Listagem 1. Script para criao dos objetos de teste.

SELECT Nome, Salario FROM Funcionarios WHERE Salario > 900

Query Optimizer Quando um comando T-SQL executado no SQL Server o Query Processor entra em ao para gerar um plano de execuo. Este plano dir qual a melhor maneira de acessar os dados gastando menos recursos e com o desempenho mais eficiente possvel. Podemos observar na Figura 1 a ao do Query Optimizer (em vermelho) e uma

srie de passos para compilar e executar um comando T-SQL. Vamos analisar melhor este comportamento. Supondo que um SELECT simples, por exemplo, SELECT * FROM Funcionarios, seja enviado ao servidor, a primeira tarefa que o Query Processor far com o comando verificar se o mesmo est no Cache Plan (mais informaes sobre o Cache Plan no final do artigo). Caso ele no esteja em cache, o Query Processor enviar o comando para os processos de Parse e Bind. O Parse/Bind executa um processo conhecido como Algebrizer. Durante este processo o SQL tenta encontrar possveis erros de escrita na sintaxe e lgica do comando. Por exemplo, o comando select id from tab1 group by nome gera uma exceo, pois a coluna id no pertence ao group by e no est utilizando uma funo de agregao (SUM, COUNT, ...). O Algebrizer tambm expande as definies do comando, isso significa que ele troca select * por select col1, col2, col3..., ou select col1 from View pelo nome das tabelas envolvidas na view. Sempre que uma view referenciada em uma consulta, o SQL Server acessa as tabelas que contm os dados. Na Figura 2,

Codificando.net e-magazine

Figura 1. Fluxograma de passos necessrios para gerar um plano de execuo.

Figura 2. Ilustrao de uma View acessando uma tabela.

www.codificando.net

Dez / Jan - 2010

54

Introduo ao Query Processor

e-magazine

por exemplo, podemos visualizar que o SQL acessa a tabela Funcionarios para ler os valores das colunas Nome e Salario. Outro passo ser resolver os nomes e tipos de objetos envolvidos na consulta. Pode acontecer de haver um sinnimo para uma determinada tabela que est em outro servidor. Quando isso acontece, o SQL precisa identificar que este sinnimo faz referncia a um objeto que est em outro banco de dados, e este banco pode estar at mesmo ligado a outro servidor utilizando um Linked Server. Aps estas anlises o Parse/Bind retorna um binrio chamado Query Processor Tree, que uma representao lgica dos passos necessrios para a execuo do comando SQL. O Query Processor Tree enviado para o prximo passo da execuo da consulta, que a anlise do Query Optimizer. importante destacar que nem sempre um comando enviado para a anlise do Query Optimizer. Por exemplo, alguns comandos DDL, tais como o CREATE Table, que so de definio das estruturas dos dados, no tm necessidade de uma anlise do Query Optimizer, pois s h uma forma de o SQL executar esta operao. Quando o Query Optimizer recebe o Query Processor Tree, ele dar inicio a uma srie de anlises a fim de encontrar qual a maneira mais eficiente de acessar os dados desejados. O Query Optimizer trabalha baseado no custo de cada operador de acesso a dados, ou seja, ele tenta encontrar a maneira que gastar menos recursos para retornar os dados. Tambm levada em considerao a velocidade de execuo da consulta, por exemplo, ele pode decidir por utilizar paralelismo a fim de retornar os dados

mais rapidamente. Ao optar por este recurso, o SQL utiliza mais de um processador para executar uma consulta. Dessa forma, o gasto com recursos se torna maior, j que mais processadores sero utilizados, porm, o tempo de retorno tende a ser menor comparado a execuo em apenas um processador. Durante a fase de anlise o Query Optimizer realiza algumas tarefas, entre elas: identificar todos os possveis argumentos de pesquisa que podem estar especificados na clusula WHERE e verificar se existem Joins entre tabelas que devem ser otimizados. Baseado nestas informaes, ele analisa quais as opes de acesso aos dados, quais ndices deve utilizar, em qual ordem os Joins devem ser realizados e qual o melhor algoritmo de Join para cada operao. Na anlise do Query Optimizer tambm existe um processo chamado Simplification, que executado logo no inicio da otimizao. Uma das tarefas do Simplification conhecida como Predicate PushDown, onde ele tenta reescrever sua consulta jogando os argumentos de pesquisa para a clusula where (veja a Listagem 2).
SELECT * FROM Funcionarios INNER JOIN Funcionarios AS
Listagem 2. Consulta com pesquisa especificados no join argumentos de

Codificando.net e-magazine

Funcionarios2 ON Funcionarios.ID = Funcionarios2.ID AND Funcionarios.Nome = 'Antonio' WHERE Funcionarios.ID > 1

Com base na consulta da Listagem 2, quando o comando for executado, durante a fase de Simplification, o SQL ir reescrever a segunda consulta deslocando o argumento de pesquisa

www.codificando.net

Dez / Jan - 2010

55

Introduo ao Query Processor

e-magazine

(Funcionarios.Nome = Antonio) para a clusula where, como pode ser visto na Listagem 3.

default, e pode ser alterado definindo a primary key como nonclustered no comando de criao da tabela. O SQL

SELECT * FROM Funcionarios INNER JOIN Funcionarios AS


Listagem 3. Consulta com argumentos de pesquisa especificados no where.

Funcionarios2 ON Funcionarios.ID = Funcionarios2.ID WHERE Funcionarios.ID > 1 AND Funcionarios.Nome = 'Antonio'

Figura 4. Execution Plan gerado pelo Query Optimizer

Na

Figura

temos

uma

simples

utilizou este ndice clustered para ler os dados da tabela Funcionarios. Veremos mais informaes sobre operadores na seo Operadores.

Figura 3. Query Optimizer.

representao grfica de como o Query Optimizer funciona. Como pode ser visto, o resultado da anlise ser o Query Plan, ou plano de execuo. Na Figura 4 podemos visualizar a representao grfica de um plano de execuo simples. Com base na estrutura da tabela Funcionarios, podemos verificar na Figura 4 que para o comando SELECT * FROM Funcionarios, o Query Optimizer gerou um plano de execuo que acessa a tabela Funcionarios utilizando o operador Clustered Index Scan. Durante a criao de uma tabela o SQL Server automaticamente cria um ndice clustered para as colunas definidas como primary key. Este o comportamento

Visualizando o Plano de execuo Existem trs maneiras de visualizar um plano de execuo: o modo grfico, modo texto e XML. Vamos analisar os dois modos mais utilizados para anlise: grfico e texto. Para visualizar o plano de execuo em modo grfico, basta digitar um cdigo TSQL no SQL Server Management Studio e pressionar ctrl+l. Neste modo diversas informaes complementares so exibidas. Estas informaes so chamadas de hints. Os hints contm informaes importantes sobre o objeto que est sendo acessado ou sobre a operao que ser executada, por exemplo, dados sobre a utilizao de memria, CPU e custo de execuo de cada operador dentro de todo o plano de execuo. Tambm so apresentados dados informando se o resultado do operador est ordenado ou no, nmero estimado de linhas que sero retornadas e
Dez / Jan - 2010

Codificando.net e-magazine
|

www.codificando.net

56

Introduo ao Query Processor

e-magazine

etc. Para exibir os hints de um determinado operador, basta posicionar o cursor do mouse sobre o operador desejado. Na Figura 5, por exemplo, podemos analisar diversas informaes em relao aos custos gerados pelo operador Clustered Index Scan. Entre elas:

Actual Number of Rows: Nmero de linhas retornadas pelo operador; Estimated I/O Cost: Valor relativo ao custo de I/O necessrio para executar o operador. desejado que este valor seja o menor possvel; Estimated CPU Cost: Valor relativo ao custo de CPU necessrio para executar o operador. desejado que este valor seja o menor possvel; Estimated Operator Cost: Este o

valor utilizado internamente pelo Query Optimizer para identificar qual ser o melhor operador a ser utilizado. O modo grfico de visualizao a maneira mais simples de analisar planos de execuo. Seguem alguns pontos que so importantes de serem destacados: Possui uma interface que facilita a visualizao dos hints e a compreenso do plano de execuo; Fcil de encontrar possveis pontos de conteno, isto , operadores que possuem alto valor de custo. Cada operador possui um valor de 0 a 100%, onde apresentada a porcentagem de custo de execuo de cada um em relao a todo o plano de execuo. Ao analisar o plano, podemos facilmente identificar quais so estes operadores; Pode ser salvo em formato XML e aberto no SQL Server Management Studio (somente SQL Server 2005 e posterior). Outra maneira de visualizar os planos de execuo utilizando o modo texto. Para habilitar a exibio do plano de execuo neste modo necessrio ativar uma das opes de ShowPlan, so elas:

Codificando.net e-magazine

Figura 5. Hint com dados do plano de execuo.

custo do operador dentro de todo o plano de execuo. Um percentual de custo exibido entre parnteses. Uma lista completa com a descrio de cada valor exibido pode ser encontrada no Help do SQL Server. Como podemos perceber, o valor exibido nas informaes de Cost um nmero sem um real sentido, pois no o custo em milissegundos, nem o nmero de IO. Este

SET SHOWPLAN_TEXT ON: Retorna o plano de execuo de cada comando do batch. Os comandos no so executados, portanto o plano de execuo o estimado, e no o atual; SET SHOWPLAN_ALL ON: Semelhante ao SHOWPLAN_TEXT, a diferena entre eles que o SHOWPLAN_ALL retorna mais informaes sobre o plano;
Dez / Jan - 2010

www.codificando.net

57

Introduo ao Query Processor

e-magazine

SET STATISTICS PROFILE ON: Retorna o plano de execuo completo, semelhante ao SHOWPLAN_ALL, com a diferena de que o PROFILE executa os comandos do batch, gerando o plano atual; SET SHOWPLAN_XML ON: Retorna o plano de execuo em um XML formatado. No executa os comandos do batch. SET STATISTICS XML ON: Semelhante ao SHOWPLAN XML, com a diferena de que o STATISTICS XML executa o batch.
Listagem 4. Exemplo de consulta e plano de execuo em modo texto.

Entretanto, muitas vezes ele a melhor maneira de se analisar o que o SQL est fazendo. Sobre este modo, os pontos que merecem destaque so: Mais fcil para analisar grandes planos de execuo, pois o plano fica bem organizado em uma rvore hierrquica. A rea de visualizao dos planos em modo grfico exige que tenhamos que ficar arrastando as barras de rolagem de um lado para o outro, tornando a anlise um pouco mais difcil; Todas as informaes j so exibidas, no precisa dos hints; Fcil para exportar para Excel ou enviar por e-mail.
Listagem 5. Exemplo de consulta e plano de execuo em modo texto.

Como exemplo, execute o comando SET SHOWPLAN_TEXT ON e depois execute a consulta SELECT * FROM Funcionarios. O resultado ser a exibio do plano de execuo em modo texto, como pode ser visto Listagem 4.
SELECT * FROM Funcionarios |--Clustered Index Scan(OBJECT: ( [dbo].[Funcionarios]. [ PK_Funciona__3214EC277D430130]))

UPDATE Funcionarios SET Nome = 50 WHERE ID = '10' UPDATE [Funcionarios] set [Nome] = @1 WHERE [ID]=@2 |--Clustered Index Update (OBJECT:( [dbo].[Funcionarios]. [PK]), SET:( [dbo]. [Funcionarios].[Nome] = [Expr1003]), DEFINE:([Expr1003] =CONVERT_IMPLICIT(varchar(30), [@1],0)), WHERE:( [dbo]. [Funcionarios].[ID] =CONVERT_IMPLICIT(int,[@2],0)))

Codificando.net e-magazine

Este plano exatamente o mesmo que visualizamos na representao grfica da Figura 4. Ele representa uma simples leitura dos dados da tabela Funcionarios, utilizando operador Clustered Index Scan, que acessa o ndice PK__Funciona__3214EC277D430130. Na Listagem 5 podemos visualizar um plano de execuo em modo texto para um update na tabela Funcionarios. Observe que o texto apresentado contm muitas funes de processos internos do SQL Server, o que acaba fazendo com que o plano fique complexo de entender.

Operadores Os cones que so exibidos nos planos de execuo (Figura 6) so conhecidos por operadores. Eles so os responsveis por executar as operaes necessrias para rodar um comando T-SQL. Existem diversos operadores e ao longo dos artigos sobre o Query Optimizer veremos mais alguns deles. Dessa forma,

www.codificando.net

Dez / Jan - 2010

58

Introduo ao Query Processor

e-magazine

vamos entender um pouco mais sobre como eles se comportam, quando e porque so necessrios. Operadores executam e calculam tarefas geradas pelo plano de execuo, por exemplo, um operador de Nested Loop executa um Join. Operadores de Index Seek fazem leitura de um range de valores em um ndice, por exemplo, uma consulta que deseja retornar os dados de uma tabela onde o valor da coluna Cdigo esteja entre 5 e 10, em uma tabela que contm registros de 0 a 100, o SQL pode usar o operador de Index Seek para ler apenas as pginas de dados do ndice que contm as linhas com os valores de 5 a 10. Operaes de agregao como MAX, MIN, SUM, COUNT e AGV so calculadas pelo operador de Stream Aggregate. O Stream Aggregate agrupa todas as linhas de uma tabela por uma ou mais colunas, calculando o valor do comando de agregao utilizado na consulta. Por exemplo, uma consulta que deseja retornar quantos pedidos os clientes fizeram em 2008 agrupado pelo nome do cliente; neste caso, o SQL ir utilizar o Stream Aggregate para agrupar todos os clientes em uma linha e calcular o SUM da quantidade de pedidos. Como j mencionado, para produzir o melhor plano de execuo o Query Optimizer analisa qual o melhor tipo de operador para executar determinada tarefa, tentando encontrar qual deles executar o processo mais rpido e/ou utilizando a menor quantidade de recursos. Todo operador executa os mtodos Open (), GetRow() e Close(). Devido a esta caracterstica, os operadores so independentes, e, por isso, o SQL consegue gerenci-los com maior facilidade. Como

no existe dependncia, um operador SORT pode ser utilizado para ordenar um resultado ou pode ser utilizado para ordenar uma coluna, a fim de saber qual o maior valor (MAX) da tabela. Isso faz com que o Query Optimizer tenha mais opes de escolha sobre qual operador utilizar. Uma caracterstica importante a ser destacada que existem duas categorias de operadores: os operadores nonblocking e os operadores blocking ou stop-and-go: Os operadores nonblocking so aqueles que lem as linhas do input e produzem o output ao mesmo tempo. No mtodo conhecido por GetRow(), conforme a leitura das linhas vai acontecendo, o operador executa sua tarefa e retorna o output para o prximo operador fazer seu trabalho. O operador de Nested Loop um bom exemplo desse comportamento. Assim que a primeira linha recebida (GetRow()) o SQL faz o Join com a tabela do outer, e caso o relacionamento seja verdadeiro a linha retornada no output. Este processo se repete at o fim da leitura da tabela do Join; J os operadores blocking necessitam primeiro ler todas as linhas (normalmente no mtodo Open()) do input para depois retorn -las para o output. Um exemplo clssico de operadores blocking o Sort, que necessita primeiro ler todas as linhas do input para fazer a ordenao e, por fim, retornar as linhas ordenadas. Existem alguns cenrios onde cada tipo de operador melhor aproveitado, por
Dez / Jan - 2010

Codificando.net e-magazine
|

www.codificando.net

59

Introduo ao Query Processor

e-magazine

exemplo, operadores nonblocking so preferveis quando utilizamos as clusulas TOP, Hint FAST N ou mesmo um Exists. Como exemplo vamos utilizar o comando Exists. Este comando utilizado para validar se um valor existe dentro de um contexto. Normalmente ele utilizado junto com subqueries para validar se um valor existe em uma tabela. Durante a execuo do Exists, se ao menos uma linha for retornada para o output, isso j caracteriza uma condio verdadeira.

Figura 6. Alguns operadores do plano de execuo.

Ou seja, se houve algum retorno, isso significa que o valor existe, e neste caso o Query Execution (responsvel por executar os planos gerados pelo Query Optimizer) encerra o processo de leitura (GetRow). Apenas uma linha o suficiente para saber se o valor procurado existe ou no. Se tivermos que esperar todas as linhas serem lidas para depois retornar o output, como os operadores blocking fazem, esta vantagem de encerrar o processo assim que encontrar alguma linha no seria aproveitada. Existem pouco mais de 100 operadores, entre eles: Scan, Compute Scalar, Aggregate, Sort, Spools e Key Lookup, apresentados na Figura 6. Para finalizar esta seo importante citar que no existe o melhor operador para fazer um Join ou uma Agregao. Cada operador melhor para uma determinada situao. Cache Como podemos observar, o processo de

gerao de um plano de execuo bem complexo e requer um tempo extra na execuo da consulta. Quanto maior e mais complexa for sua consulta, mais tempo o Query Processor leva para analisar todas as variantes, e por fim gerar um plano de execuo para o comando TSQL. Toda essa operao de gerar o plano de execuo causa delay e normalmente faz alto uso de CPU. Por isso, o SQL Server usa um mecanismo para evitar que toda vez que uma consulta for enviada para o banco, o Query Processor tenha que gerar um novo plano de execuo. justamente este o papel do Cache Plan: evitar que uma consulta que j tenha passado pelo Query Optimizer seja enviada novamente para otimizao. Conforme podemos observar no fluxograma (Figura 1), o primeiro processo que o Query Processor faz procurar no cache se j existe um plano de execuo para a consulta enviada ao servidor. Isso significa que quando um plano de execuo gerado para uma determinada consulta, o SQL grava este plano em uma rea de memria a fim de reutilizar o mesmo plano de execuo para consultas semelhantes. A rea de memria utilizada para armazenamento dos planos de execuo exatamente a quantidade de memria disponvel para uso do servidor SQL Server. No SQL Server 7.0 havia uma rea especfica para o armazenamento dos planos, chamada procedure cache. Porm, a partir da verso 2000 isso foi alterado para que o SQL pudesse utilizar toda a memria disponvel ao SQL Server. Na verdade, no SQL Server 7.0 s eram armazenados planos de execuo de procedures (por isso se chamava procedure cache), consultas ad-hoc no
Dez / Jan - 2010

Codificando.net e-magazine
|

www.codificando.net

60

Introduo ao Query Processor

e-magazine

tinham o plano armazenado em cache. Reutilizando planos de consulta Em muitas ocasies, reutilizar o plano de execuo pode ser uma grande vantagem, j que economizamos todo o tempo que seria gasto pelo Query Processor para analisar um novo plano. Entretanto, reutilizar um plano de execuo que est armazenado em cache pode ser um problema, pois nem sempre a mesma consulta retorna a mesma quantidade de dados. Por isso, o SQL Server bem cauteloso quando estamos falando de reutilizao de planos de execuo, j que pode haver situaes onde um mesmo plano no seja o ideal para consultas parecidas. Por exemplo, vamos imaginar que uma consulta que retorna apenas 10 linhas seja enviada pela primeira vez para o SQL Server, e o Query Processor gerou um plano de execuo que utiliza um ndice nonclustered mais um bookmark para ler uma pequena quantidade de registros. Nestas condies o Query Engine executa este plano e depois o armazena em cache. Agora imagine que uma nova consulta, igual primeira, seja enviada para o SQL Server, mas desta vez a condio de busca informada no where requeira que milhares de linhas sejam retornadas. Se o SQL optar por reutilizar o plano de execuo isso no vai ser bom, pois bem provvel que seja melhor fazer um Scan em toda a tabela do que utilizar o ndice mais o bookmark. O cenrio descrito bastante comum de acontecer. Outro fator importante de ser observado que algumas operaes podem deixar um plano que est em cache desatualizado. Por exemplo, pode acontecer do schema

que envolve a consulta ser alterado, ou um novo ndice ser criado ou at mesmo apagado. Nestas situaes o SQL no conseguir reutilizar o plano de execuo, o que resulta em uma nova anlise do Query Processor. Existem diversas maneiras de saber se um plano de execuo foi reutilizado ou no. Para isso abra uma consulta no SQL Server Management Studio e execute o cdigo da Listagem 6. Na primeira linha executado um comando (DBCC FREEPROCCACHE) para limpar a rea de cache atual, apagando todos os planos de consulta que esto armazenados em memria. Feito isso, so executadas trs simples consultas para retornar os dados de um determinado funcionrio especificado na clusula where. Por fim, selecionamos os registros da sys.dm_exec_cached_plans, que uma view do sistema que retorna os planos de execuo que esto em cache. Esta view retorna uma coluna chamada plan_handle que do tipo binrio. Para converter este valor binrio para um texto, o SQL disponibiliza uma function do sistema chamada sys.dm_exec_sql_text.
Listagem 6. Exemplo de consulta e acesso ao cache plan.

Codificando.net e-magazine

Ela l uma entrada em binrio e retornar uma coluna chamada text, que contm o Use Cac Cou heO nts bjTy pe Compil 1
ed Plan

Ob jty pe
Ad hoc Ad hoc

Comando_SQL

Compil ed Plan

SELECT * FROM Funcionarios WHERE Nome = 'Antonio' SELECT * FROM Funcionarios WHERE Nome = 'Jos'

Tabela 1. Valores que esto em cache retornados pela DMV sys.dm_exec_cached_plans.

www.codificando.net

Dez / Jan - 2010

61

Introduo ao Query Processor

e-magazine

plano em modo texto.


DBCC FREEPROCCACHE; GO SELECT * FROM Funcionarios WHERE Nome = 'Jos' GO SELECT * FROM Funcionarios WHERE Nome = 'Antonio' GO SELECT * FROM Funcionarios WHERE Nome = 'Jos' GO SELECT usecounts, cacheobjtype, objtype, "text" AS Comando_SQL FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text (plan_handle) WHERE cacheobjtype = 'Compiled Plan' AND "text" NOT LIKE '% dm_exec%';

O resultado do comando acima deve ser parecido com os registros da Tabela 1. A DMV (Dynamic Management Views) sys.dm_exec_cached_plans retorna todos os planos de execuo que esto armazenados no cache do SQL Server. Voc pode utilizar esta view para saber se um determinado plano foi reutilizado ou no, a quantidade de memria que um plano est utilizando e tambm para verificar quantas vezes um plano foi reutilizado. A coluna UseCounts retorna a quantidade de vezes em que o plano de execuo foi reutilizado. A coluna CacheObjType retorna o tipo do objeto em cache. Ela pode apresentar os seguintes valores:

Plan Sub no cache, no com o plano completo, mas somente com um Plan Sub. Isso vai permitir que o SQL reconhea que um plano j foi gerado para esta consulta. A partir da segunda execuo deste comando, o SQL substitui este plano pelo plano completo; Parse Tree: Representa o parse de uma view, function, etc.; Extended Proc: Grava o plano para extended procedures, por exemplo, a xp_cmdShell; CLR Compiled Func: Funes criadas utilizando CLR; CLR Compiled Proc: Procedures criadas utilizando CLR.

Compiled Plan: Representa um plano de execuo completo; Compiled Plan Sub: Existe uma propriedade do banco chamada optimize for ad hoc workloads. Quando habilitada, assim que uma consulta AdHoc enviada pela primeira vez ao SQL, ele grava um

A coluna Objtype retorna qual o tipo do objeto que est armazenado, por exemplo, pode ser um comando Adhoc, proc, view, trigger, entre outros. Observe na Tabela 1 que a coluna UseCounts contm o valor 2 para a consulta SELECT * FROM Funcionarios WHERE Nome = 'Jos', mostrando que o SQL Server utilizou duas vezes o mesmo plano de execuo. Uma observao importante em relao ao cache plan que para consultas adhoc, que no estejam parametrizadas (ou seja, iguais a que utilizamos acima), para que o Query Processor consiga fazer proveito do plano que est em cache as consultas precisam ser escritas exatamente iguais. Inclusive os valores no where tero que ser os mesmos. Repare que no exemplo da Listagem 6 o SQL s reutilizou o plano de execuo em cache porque a terceira consulta enviada para o servidor idntica primeira consulta, inclusive o WHERE Nome = Jos. Isso significa que cada caractere ser
Dez / Jan - 2010

Codificando.net e-magazine
|

www.codificando.net

62

Introduo ao Query Processor

e-magazine

analisado e comparado com o comando em cache. Uma simples quebra de linha ou uma letra maiscula ou at mesmo um cdigo de comentrio j ser o suficiente para inviabilizar o uso do plano em cache, acarretando na criao de um novo plano de execuo. Parametrizao Sempre que possvel o SQL Server tenta alterar sua consulta para torn-la apta reutilizao dos planos de execuo. Este comportamento chama-se parametrizao. Consultas parametrizadas tm mais chances de terem seu plano de execuo reutilizado. No SQL Server 2005 existem dois tipos de parametrizao, o Simple Parameterization (conhecido como auto-parameterization, no SQL Server 2000) e Forced Parameterization. Ao utilizar a parametrizao Simple, o SQL mais cauteloso em relao s quais consultas parametrizar, j a opo forced tenta parametrizar a maior quantidade de consultas possvel. Quando um banco de dados criado o padro de parametrizao o Simple. Para alterar esta opo acesse as propriedades do banco de dados e selecione a opo Forced na propriedade Parameterization. Quando a opo Forced est selecionada o SQL tenta parametrizar a maior quantidade de consultas possveis. Existe uma lista de instrues que impedem o uso de parametrizao. Esta lista pode ser acessada no help do SQL Server. Durante o processo de parametrizao o SQL Server tenta alterar o valor no where por uma varivel, e futuramente ele altera este valor pelo novo valor informado na consulta.

O SQL Server bem cauteloso em relao a quando parametrizar uma consulta. Este processo somente ser adotado para consultas que so consideradas seguras. Uma consulta segura quando o plano selecionado no muda caso os parmetros (filtros) mudem. Vejamos um exemplo de consulta considerada segura: Para uma consulta que busca por um valor em uma tabela, passando um filtro para uma coluna que contm um ndice nico, o SQL sabe que apenas um valor ser retornado. Independente do valor do parmetro recebido, pois a presena do ndice nico obriga que exista apenas um registro com o mesmo valor em toda a tabela. Vejamos um exemplo de consulta considerada no segura: Fazer um seek, ou seja, ler um range de informao a partir de um ndice pode ser uma tima escolha. Por outro lado, utilizar este mesmo plano para uma consulta que retorna vrias linhas pode no ser a melhor opo.

Codificando.net e-magazine
|

Vamos analisar um exemplo de parametrizao e reutilizao do plano de execuo. Para isso execute o cdigo da Listagem 7. Neste cdigo, executamos duas simples consultas que retornam os dados dos funcionrios, com base no ID especificado na clusula where. Como a coluna ID a chave primria da tabela Funcionarios, os valores de ID no podem se repetir. Isso caracteriza esta consulta como segura para reutilizao do plano de execuo. Podemos observar na Tabela 2 que o SQL reutiliza o mesmo plano para as duas consultas.
Dez / Jan - 2010

www.codificando.net

63

Introduo ao Query Processor

e-magazine

Use Cac Cou heO nts bjT ype 1 1 2


Compil ed Plan Compil ed Plan Compil ed Plan

Ob Comando_SQL jty pe
Ad hoc Ad hoc Pre par ed SELECT * FROM Funcionarios WHERE ID = 2 SELECT * FROM Funcionarios WHERE ID = 1 (@1 tinyint)SELECT * FROM [Funcionarios] WHERE [ID]=@1

Tabela 2. Valores que esto em cache retornados pela DMV sys.dm_exec_cached_plans.

SELECT WHERE GO SELECT WHERE GO

* FROM Funcionarios ID = 1 * FROM Funcionarios ID = 2

um plano de execuo prepared e ele foi utilizado duas vezes. As outras consultas continuam aparecendo, mas elas no contem o plano de execuo, elas apontam para a linha que tem o plano de execuo prepared. Infelizmente com as DMVs e recursos disponibilizados pelo SQL Server, no possvel visualizar esta ligao entre os planos Adhoc e o plano Prepared, este um cdigo interno do SQL. Estas consultas Adhoc so conhecidas como Shell Queries, elas so armazenadas para agilizar o processo de reutilizao do plano. Veja na Figura 7 um exemplo de como estas consultas podem ajudar na performance da execuo do comando.

SELECT usecounts, cacheobjtype, objtype, "text" AS Comando_SQL FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text (plan_handle) WHERE cacheobjtype = 'Compiled Plan' AND "text" NOT LIKE '% dm_exec%';
Listagem 7. Exemplo de consulta parametrizada. Figura 8. Exemplo de consulta parametrizada.

Codificando.net e-magazine

Figura 7. Fluxograma de procura por plano de execuo em cache.

Como podemos observar nas colunas UseCounts e Objtype, o SQL Server gerou www.codificando.net
Dez / Jan - 2010

64

Introduo ao Query Processor

e-magazine

Nesta figura podemos observar que quando um mesmo comando for executado, caso ele contenha um shell query no cache, o SQL pula uma etapa do processo de localizao do plano. Observe na Tabela 2 que a linha 3 possui o plano de execuo parametrizado, que o plano prepared. O plano prepared foi gerado baseado nas consultas executadas pelo cdigo da Listagem 7. Como podemos observar, o SQL Server trocou o valor no where por uma varivel @1 e declarou a varivel como datatype tinyint. Ao parametrizar uma consulta o SQL tenta encontrar qual a melhor opo de varivel a ser utilizada, neste caso, ele optou pelo tinyint por ela ocupar apenas 1 byte de armazenamento. O datatype tinyint consegue tratar valores de 0 a 255, isto , caso o valor informado no where seja 300 o SQL no conseguir utilizar este plano de execuo, causando uma nova recompilao do comando. Na Figura 8 podemos visualizar como funciona o conceito de parametrizao. Ao parametrizar o valor de where Prikey, o SQL consegue reutilizar o mesmo plano de execuo para as trs consultas apenas alterando o valor de ?.

grfico e modo texto. Por ltimo foi apresentado o conceito de Cache Plan e parametrizao de consultas. Linked Server: um mecanismo que permite que o SQL Server execute comandos em outro banco de dados OLE DB. Ao criar um linked Server o SQL cria uma conexo com o banco de dados destino, permitindo que os dados que esto armazenados no banco destino sejam acessados a partir da prpria instancia do SQL Server. Por exemplo, possvel abrir uma consulta no SSMS e fazer um update em uma tabela do SQL Server lendo os dados de uma base Oracle. O banco utilizado no Linked Server pode ser remoto ou local. Podemos criar um linked Server com um banco de dados Access, Oracle, MySQL, ou qualquer banco de dados que contenha um driver OLE DB. OLE DB: (Object Linking and Embedding, Database) um pacote que contm as informaes necessrias para conexo e gerenciamento da leitura dos registros armazenados em uma fonte de dados (arquivos txt, xls, entre outros) ou bancos de dados. Fabiano Neves Amorim
(fabiano_amorim@bol.com.br) Certificado MCP, MCTS e MCITP Database Developer em SQL Server 2000/2005, Especialista em desenvolvimento de Data Warehouses e Tunning de banco de dados SQL Server. Palestrante de WebCasts para Microsoft Brasil, participante ativo de fruns MSDN e TechNet, escreve artigos sobre SQL Server para as revistas SQL Magazine, Codificando.net e para o site Simple-Talk. Mantenedor de blog tcnico sobre Tecnologia e SQL Server (http://fabianosqlserver.spaces.live.com). Atualmente trabalha na CNPM empresa certificada MPS.BR e Gold Certified Partner Microsoft.

Codificando.net e-magazine

Concluso Vimos neste artigo quais os mtodos que o SQL Server utiliza para executar uma consulta SQL e como o Query Processor trabalha para acessar os dados armazenados nos arquivos de banco de dados. Ao acessar os dados, estudamos um pouco dos operadores de acesso a dados, bem como os tipos de operadores. Tambm vimos como analisar um plano de execuo e as anlises em modo

www.codificando.net

Dez / Jan - 2010

65

e-magazine

Codificando.net e-magazine
|

www.codificando.net

Dez / Jan - 2010

66

e-magazine

ASP .NET Core Web Forms ou MVC?


Por: Alexandre Tarifa
Este artigo no tem como objetivo apresentar profundamente as questes tcnicas sobre cada tecnologia e sim sobre o ponto de vista de quais os melhores cenrios para a aplicao delas. Para informaes tcnicas, o site www.asp.net trs todo o contedo em diversos tipos de formatos (artigos, vdeos, passo-a-passo, etc). Eu costumo dividir o desenvolvimento Web em dois tipos de desenvolvimentos: sistemas e sites. Desenvolvimento de sistemas Normalmente executado dentro de um ambiente conhecido e controlado, possui uma quantidade pequena de usurios (200 pessoas por exemplo), fcilmente controlado com pr-requisitos (para executar utilize o Internet Explorer 7 ou superior na resoluo XYZ) e executa processos administrativos, comerciais com um foco muito grande na implementao do negcio, ou seja, praticamente todo o sistema est desenvolvido dentro de uma camada de negcios/dados/banco de dados. Neste cenrio, no existe preocupao alguma com layout, HTML, resoluo, etc etc etc.. e at mesmo totalmente ignorado usurios com baixa velocidade de conexo com internet, padres W3C, etc. Este cenrio muito comum em sistemas internos (seja rodando na intranet ou internet). As principais preocupaes so: implementao dos requisitos de negcio, segurana, performance de processamento, infra-estrutura e distribuio. Dificilmente nesse cenrio existe a figura de um designer. Na minha experincia de consultoria, esse o cenrio mais comum nas empresas. Desenvolvimento de sites A dificuldade muito superior em relao a camada de apresentao e claro, as implementaes de negcios devem ser integras conforme as especificaes e definies de negcio de cada empresa. Neste cenrio existe a necessidade de se rodar em qualquer lugar (navegador de mercado), performance da camada de apresentao necessria, provavelmente poucos processamentos pesados em servidor, necessidade de seguir os padres W3C, recursos no client para melhorar a experincia com o usurio, a figura do designer presente, at mesmo conhecimento pesado em HTML necessrio e a integridade do layout X aplicao algo extremamente trabalhoso. Web Forms ou MVC

www.codificando.net

Abril //Maio-2009 Dez Jan 2010

67

e-magazine
ASP.NET Core plataforma NICA da Microsoft para criao de aplicaes Web. Os recursos do ASP .NET esto implementados aqui! Logo, Web Forms e MVC oferecem os mesmos recursos Core. Web Forms - temos uma plataforma extremamente produtiva em questes de controles prontos, validao de dados de formulrios, criao de formulrios, etc. Alm de total controle do ciclo de carregamento da pgina, oferece uma plataforma para os desenvolvedores ideal para o desenvolvimento de sistemas. J para desenvolvimento de sites, pode trazer algumas dificuldades, principalmente no controle do HTML (em alguns casos temos que abrir mo da produtividade para controlar 100%), misso complicada de controlar/diminuir o tamanho do View State, que pode ser muito ruim em sites, resumindo, para desenvolvimento de sites podemos considerar que uma plataforma boa porm com restries de controle e produtividade. MVC temos uma plataforma que pode ser totalmente controlada pelo desenvolvedor, porm algumas implementaes de produtividade disponveis no Web Forms ainda no esto disponveis. Sugere a utilizao de um padro, no caso o MVC (diviso de papeis, testvel,etc), mas claro, no garante de forma alguma que isso ser seguido, mas j faz com que as pessoas pensem em us-lo. Para desenvolvimento de sistemas considero uma plataforma boa, porm com alguns prejuizos de produtividade e que talvez em algumas www.codificando.net
Abril //Maio-2009 Dez Jan 2010

empresas ser totalmente repreendido por misturar o cdigo HTML com o cdigo da lgica da interface (claro que se for seguido o padro, estamos falando de pouco cdigo aqui!). J para desenvolvimento de sites a plataforma ideal pois o desenvolvedor tem todo o poder de controlar 100% as suas necessidades. Verses Web Forms Chega no framework 4.0 e Visual Studio 2010 na verso 4, a verso atual em produo a 3.5. MVC Chega no framework 4.0 e Visual Studio 2010 na verso 2, a verso atual em produo a 1.0. Resumo A Microsoft est criando um leque, hoje temos duas possibilidades, Web Forms e MVC, e quem sabe futuramente no teremos mais... vale sempre lembrar que o Core ser o mesmo, proporcionando uma evoluo constante nas duas tecnologias

68

Você também pode gostar