Você está na página 1de 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Conceitos prticos de Programao e Tunning no Microsoft SQL Server 2000.

Base de Conhecimento.

Com foco no Sistema SISE em produo.

Alessandro Bornato DBA - Sistran

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Introduo:
Nossa vivncia no ambiente de produo do Sistema SISE, no cliente Bradesco, tem nos mostrado resultados que precisamos absorver positivamente. Esse documento foi criado com base na vivncia da soluo de problemas e de tunning efetuados em objetos que, de alguma forma, no atendiam necessidade da aplicao quando submetido ao ambiente de produo. Ou seja, rotinas que fomos obrigados a reescrev-las para uma funcionalidade correta. Veremos tambm, exemplos de como proceder desde o momento do desenvolvimento, sempre focando o ambiente de produo. As queixas quanto ao tempo de resposta, usualmente denigrem bons trabalhos de programao da aplicao, deixando todas as qualidades da mesma ofuscadas. importante para a soluo do problema de performance saber qual a origem do consumo excessivo de recursos do servidor, essa justamente nossa dificuldade. Algumas solues que adotamos para contornar o problema de performance, nem sempre seguem as melhores prticas. Mas isso no ruim, muito pelo contrrio, a variedade de cenrio que existe, exige um jogo de cintura diferente. Mas todas as possibilidades devem ser massivamente testadas e avaliadas para que em momentos oportunos possamos justificar tal soluo. A documentao de cdigo nesses casos vital. Claro, nem todas as melhores prticas podem ser descartadas, h casos em que obviamente a boa prtica insubstituvel. Quando o foco performance podemos avaliar as opes. Porm, em casos de padres de desenvolvimento, lgica clara, objetos compactos, etc, no devem jamais ser postos de lado. Em geral podemos dizer: - A regra definitiva da certeza de ganho de performance no existe. - Nunca tomar nada como verdade certa. Com base nessas afirmaes a dvida que surge inevitvel: Por que, ento, devemos agir seguindo as boas prticas?. Devemos conhec-las para aplic-las como soluo default, ento testar, analisar e se possvel, reavaliar as prticas paralelas adotadas no dia-a-dia, mesmo as que boicotam as boas prticas drasticamente. claro que isso deve ser seguido de maneira moderada e inteligente. Acredito que voc no tomaria toda cerveja do bar porque um amigo te disse que isso curou a cirrose do pai dele. Certo? Com exageros parte, fique atento casos de sucesso utilizando uma tcnica ou outra. O uso do jargo cada caso um caso, se aplica perfeitamente aqui. Os diversos cenrios em que nos deparamos exigem um jogo de cintura especfico. Ser visionrio, considerar todo o cenrio produtivo em que seu cdigo ser submetido, uma regra de ouro.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
ndice
Introduo: .......................................................................................................................................................................................................2 SQL-ANSI..........................................................................................................................................................................................................4 ALIAS ...............................................................................................................................................................................................................4 EXEC string......................................................................................................................................................................................................4 Cdigo SQL Injetado Ataque Hacker .............................................................................................................................................................4 Entrada do Hacker ........................................................................................................................................................................................4 DISTINCT .........................................................................................................................................................................................................4 SET NOCOUNT ON .............................................................................................................................................................................................4 ORDEM de relacionamento..................................................................................................................................................................................4 LEFT JOIN.........................................................................................................................................................................................................4 Comando versus Procedimento Armazenado e Vises .............................................................................................................................................4 COUNT(*), IF EXISTS() e @@ROWCOUNT............................................................................................................................................................4 HAVING E GROUP BY versus WHERE....................................................................................................................................................................4 Ordenar dados - GROUP BY versus ORDER BY.......................................................................................................................................................4 Cursores ...........................................................................................................................................................................................................4 Cursores versus Variveis tipo Tabela ...................................................................................................................................................................4 SET ..................................................................................................................................................................................................................4 Lista de SET que podem causar recompilao nas Procedures: ...........................................................................................................................4 Lista de SET que NO causam recompilao nas Procedures: .............................................................................................................................4 Questo:......................................................................................................................................................................................................4 Transaes / @@TRANCOUNT ............................................................................................................................................................................4 CONSTRAINT versus TRIGGER ............................................................................................................................................................................4 COVERING INDEX e VIEW Indexada.....................................................................................................................................................................4 TOP n / SET ROWCOUNT n .................................................................................................................................................................................4 Relevncia: Baixa...............................................................................................................................................................................................4 HINT de ndices (INDEX=XXXX) ..........................................................................................................................................................................4 HINT de modo de leitura (NOLOCK) .....................................................................................................................................................................4 COALESCE e ISNULL versus CASE WHEN ..............................................................................................................................................................4 Tabelas temporrias...........................................................................................................................................................................................4 Exemplo de mal uso de preenchimento de temporria: ......................................................................................................................................4 Tabela de recompilao de acordo com Qtde de registros em temporrias: ..........................................................................................................4 Controvrsia:................................................................................................................................................................................................4 Controvrsia 2: .............................................................................................................................................................................................4 Dica geral para a adoo de criao de tabelas temporrias: ..............................................................................................................................4 Seqncia / Auto-numerao..........................................................................................................................................................................4 Procedure com Parmetro Multivalorado (uso de XML) ...........................................................................................................................................4 CONVERT / CAST / SARG ....................................................................................................................................................................................4 SARG...........................................................................................................................................................................................................4 NOT IN, IN, EXISTS e NOT EXISTS ......................................................................................................................................................................4 IN versus OR.....................................................................................................................................................................................................4 FRAGMENTAO DE OBJETO ..............................................................................................................................................................................4 Dicas Gerais ......................................................................................................................................................................................................4 Criao de Vises ou Funes para comportar regras de negcio ........................................................................................................................4 Requisitos para criao de views indexadas ......................................................................................................................................................4 Requisito Administrativo ............................................................................................................................................................................4 Plano de Execuo - Fundamentos: .................................................................................................................................................................4 Pr-requisitos antes de cada execuo (Importante) .....................................................................................................................................4 Primeiro Ponto: Operaes com alto percentual de consumo..........................................................................................................................4 Segundo ponto: Table Scan, Index Scans e Clustered Index Scans .................................................................................................................4 Terceiro ponto: Warnings ..........................................................................................................................................................................4 Quarto ponto: Seta muito grossa................................................................................................................................................................4 Quinto Ponto: Bookmark Lookups...............................................................................................................................................................4 Sexto Ponto: Sorting.................................................................................................................................................................................4 Cenrio para estudo: ..........................................................................................................................................................................................4 Medio simples em milesegundos. ......................................................................................................................................................................4 Profiler e Index Wizard .......................................................................................................................................................................................4 USANDO O PROFILER ....................................................................................................................................................................................4 O que Monitorar............................................................................................................................................................................................4 Filtrar o Resultado .........................................................................................................................................................................................4 Aes Index Wizard ....................................................................................................................................................................................4 Consideraes Finais ..........................................................................................................................................................................................4

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

SQL-ANSI
Relevncia: Alta (Maleabilidade, no influencia em performance) Os softwares de bancos de dados (SGBDs) em geral, como ORACLE e SQL Server, seguem os critrios estabelecidos e definidos oficialmente pelo Instituto de padres nacionais americanos (ANSI). Porm existe tambm a forma nativa de codificao em cada um deles: ORACLE (9i e posterior) MS-SQL SyBase DB2 PL/SQL T-SQL T-SQL DB2 SQL dialect

O SQL-ANSI garante portabilidade entre os diversos fornecedores de software de banco de dados do mercado. E a variante nativa de cada um deles de uso exclusivo e personalizado. A recomendao sempre utilizar o padro ANSI, de preferncia ANSI-92. Exemplo de transact-SQL em SQL-Server (no SQL-ANSI):
select modg.id_origem, from rgr_mod_geral as rgr_regra as where modg.cd_regra *= regra.NM_REGRA, modg.cd_modulo modg, regra regra.cd_regra

Esse cdigo no compatvel com o ORACLE ou DB2. Pois est no padro Transact-SQL (TSQL), que adotado por alguns SGBDs apenas, como SQL-Server e Sybase. Nossa certificao em andamento (PMO) exige o uso de padres. Esse apenas um dos itens abordados nessa certificao. Em breve teremos toda a documentao necessria para o uso adequado, por ora, siga as recomendaes e quando no houver, siga o bom senso ou procure suporte com a equipe DBA.

SELECT *
Relevncia: Alta Restringir o resultado para retornar somente as colunas necessrias das tabelas, nunca todas as colunas. Isso reduz o trfego de rede. E muitas vezes, evita o LOCK na tabela. NUNCA utilizar SELECT *. Pois pode ocasionar em LOCK em toda tabela. E a chance de um TABLE SCAN ou CLUSTERED INDEX SCAN (leitura varrida em toda tabela ou ndice) grande.

ALIAS
Relevncia: Baixa (Boa prtica, no influencia em performance) Sempre usar ALIAS nas tabelas para facilitar a leitura do cdigo, evitando erros na interpretao. O padro de ALIAS serve para que em todas as referncias s tabelas sejam atribudos mesma nomenclatura, facilitando assim a interpretao.
/*Exemplo 1 - No faa isso*/ select rgr_mod_geral.id_origem, rgr_regra.NM_REGRA, rgr_mod_geral.cd_modulo from rgr_mod_geral as rgr_mod_geral inner join rgr_regra as rgr_regra on rgr_mod_geral.cd_regra = rgr_regra.cd_regra where rgr_mod_geral.cd_regra = 38 and rgr_mod_geral.cd_modulo = 'PRP'

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Ocorre normalmente quando a procedure derivada de um extinto statement do DICT. No deve ser simplesmente copiado o cdigo do DICT e colado na nova procedure. Aplique o ALIAS a cada tabela envolvida.
/*Exemplo 2 - Boa prtica*/ select modg.id_origem, regra.NM_REGRA, modg.cd_modulo from rgr_mod_geral as modg inner join rgr_regra as regra on modg.cd_regra = regra.cd_regra where modg.cd_regra = 38 and modg.cd_modulo = 'PRP'

Nossa certificao em andamento (PMO) exige o uso de padres. Esse apenas um dos itens abordados nessa certificao.

EXEC string
Relevncia: Alta Nunca utilizar EXEC. (comandos montados dinamicamente). Motivos: 1) Essa prtica fora o SQL a traar um plano imediato em todo momento que a procedure for utilizada. 2) A procedure sempre ser recompilada. 3) O comando ser descoberto pelo SQL somente no momento da execuo. Mistrio at ento. 4) O usurio precisar ter permisso de acesso s tabelas envolvidas na string de comandos. 5) Cada tentativa de ao (oculta nesse cdigo secreto) ser avaliada a permisso necessria (INSERT, UPDATE, DELETE) Em uma procedure que possui o cdigo aberto (sem EXEC) bastaria o usurio receber a permisso de execuo na procedure, sem necessidade de permisses especficas nas tabelas que constarem no corpo desse objeto. Os statements executados ficam no cache do SQL, ocupam espao significativo. Esse espao poderia ser utilizado por comandos mais compactos (Procedures, Views). O EXEC string funciona bem se a string a ser executada for um objeto do tipo Procedimento Armazenado. Pois esse j se encontra compilado e com possibilidade de plano de execuo j disponvel. Exemplo:
Declare @UP varchar(255), @cd_regra int, @id_regra bigint set @cd_regra=180 set @id_regra=6338 SELECT @UP = nm_select_body from rgr_template where cd_regra = @cd_regra EXECUTE @UP @id_regra

A varivel @UP receber o nome do procedimento (neste caso UP_RESGATA_REGRA_180) que est armazenado na coluna da tabela RGR_TEMPLATE. Executar a mesma e no haver recompilao e o plano de execuo da procedure j existir.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Cdigo SQL Injetado Ataque Hacker


O conceito SQL Injection um mtodo de explorar bases de dados atravs da interface com o usurio aliado ao EXEC dinmico. O mtodo conta com a vantagem do fato que o SQL permite comandos mltiplos em uma nica solicitao, separada por delimitador. Aproveita-se tambm da maneira que o SQL trata os caracteres de isolamento de string . Imaginemos agora um cenrio fictcio: Temos um login no SQL para o usurio local de ASPNET e com direitos de Administrador (dbo) em Northwind. Um dos colaboradores da companhia escreve ento um webform simples no incio de uma sesso em ASP.NET que pede usurio e senha, com validao na tabela de Test_Logins:
Private Sub LoginButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LoginButton.Click Dim success As Boolean = False Dim sqlcon As New System.Data.SqlClient.SqlConnection("SERVER=(local);" & _ "INITIAL CATALOG=Northwind;" & _ "INTEGRATED SECURITY=SSPI;") sqlcon.Open() Dim sqlstr As String = "SELECT * " & _ "FROM Test_Logins " & _ "WHERE UserName = '" & Username.Text & "' " & _ "AND Password = '" & Password.Text & "'" Dim sqlcmd As New System.Data.SqlClient.SqlCommand(sqlstr, sqlcon) Dim sqldr As System.Data.SqlClient.SqlDataReader = sqlcmd.ExecuteReader() If sqldr.HasRows Then success = True sqldr.Close() sqlcmd.Dispose() sqlcon.Dispose() If success Then Server.Transfer("Success.aspx") End Sub

O cdigo para login em 5 passos bsicos: 1- Usurio digita seu nome e senha; 2 - O Web Form abre a conexo na base Northwind ; 3 O Web Form contri dinamicamente o comando SELECT * FROM Test_Logins WHERE UserName = 'usurio' AND Password = 'Senha' ; 4-O Web Form submete o commando para a conexo do SQL; 5- If existir alguma linha nesse resultado, ento o usurio conhecido e poder acessar.

Entrada do Hacker
Um hacker qualquer (vamos cham-lo de Franco) recebe um carto de visita de um funcionrio qualquer da empresa (vamos cham-lo de Luiz Garcia), e nesse carto consta (Vice Presidente de Vendas). Ento nosso hacker se assanha a provar suas habilidades, executando qualquer ao no site de vendas da empresa e quem sabe ter acesso a alguma informao privilegiada e teoricamente restrita. O exemplo a seguir simples, porm representa uma porta de entrada para ataques hacker. O primeiro passo para o ataque descobrir o login do usurio, em posse do carto do vice-presidente as possibilidades de acertos aumentam. Ento imaginemos que Franco acerte o usurio. Falta s descobrir a senha, difcil?
Digite seu nome e senha para acessar o sistema: Usurio: LGARCIA;--;-Senha : [OK]

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

O resultado da montagem do comando seria: SELECT * FROM Test_Logins WHERE UserName = 'lgarcia'; -- AND Password = '' Reparem que o hacker usou de um primeiro artifcio, antecipou a montagem da string dinmica e garantiu o isolamento subseqente que o prprio formulrio iria montar. Dessa forma o usurio foi validado sem mesmo o confronto da senha. Alternativamente, Franco poderia ainda inserir comandos como DROP, DELETE ou qualquer outro comando transact-SQL para produzir resultados intrusivos ou destrutivos. Poderia ainda acessar o procedimento extendido do SQL (xp_cmdshell) e executar comandos na rede corporativa.
Digite seu nome e senha para acessar o sistema: Usurio:; DELETE FROM Test_Logins;---Senha : [OK] Digite seu nome e senha para acessar o sistema: Usurio:; DROP TABLE Test_Logins;-Senha : [OK] Digite seu nome e senha para acessar o sistema: Usurio:; EXEC xp_cmdshell ;-Senha : [OK]

DISTINCT
Relevncia: Alta Tentar evitar o uso da clusula DISTINCT, sempre que possvel. Essa clusula ir resultar em degradao de performance, usar somente em ltimo caso, quando no houver outra forma. S remover duplicidades quando houver a possibilidade de duplicatas no conjunto resultado.

SET NOCOUNT ON
Relevncia: Mdia Usar o comando SET NOCOUNT ON nas Procedures para conter as mensagens de indicao de nmero de linhas afetadas pelos comandos T-SQL. Isso pode reduzir o trfego na rede, porque o cliente no receber mensagens indicando as linhas afetadas pelos comandos.

ORDEM de relacionamento
Relevncia: Alta Na montagem das tabelas envolvidas numa query procure saber qual tabela tem maior relevncia para posicion-la ao topo. Isso vai depender da lista de campos no SELECT e tambm da lista de campos em ORDER BY, GROUP BY e HAVING.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Definir datatype dos campos utilizados nas comparaes de forma que sejam idnticos aos da tabela.

LEFT JOIN
Relevncia: Mdia Se concluir que a tabela que contm mais registros deve ficar no topo e usada como base, utilize as demais com LEFT JOIN para ganhar performance. Tente ao MXIMO quebrar o cdigo em mais de uma parte, obtendo assim pequenas partes que geraro um ou mais Procedimento Armazenado. Tentar utilizar subqueries em queries extensas. O ganho de performance com a clusula LEFT JOIN obtida assim: O compilador do SQL necessita saber apenas um dos lados, ou seja, no existe confronto em ambas as tabelas para fazer descarte. Todos os registros do lado esquerdo sero listados e consecutivamente os da direita, quando existirem. Isso poupa, em muitos casos segundos preciosos. Para que essa tcnica funcione, garanta que a tabela da esquerda (tabela guia) possua clusula WHERE e se no so aceitos nulos vindos da tabela da direita, deve-se tratar essa condio adequadamente.

Comando versus Procedimento Armazenado e Vises


Relevncia: Alta Sempre utilizar Procedimento Armazenado ou Vises. Isso reduz o trfego na rede, porque o cliente ir enviar ao servidor somente o nome dos objetos. Reduz ainda a administrao com as permisses que teramos que conceder para uso de objetos para formulao dos comandos para acessar, alterar, deletar e inserir dados. O DICT um caso tpico de uso de comandos, monta dinamicamente o comando e solicita ao SQL a execuo.

COUNT(*), IF EXISTS() e @@ROWCOUNT


Relevncia: Mdia Se for preciso retornar o total de linhas de uma tabela, voc pode usar outro mecanismo, ao invs do comando SELECT COUNT(*). O uso do SELECT COUNT(*) faz um FULL TABLE SCAN ou CLUSTERED INDEX SCAN para retornar o total de linhas na tabela. Podemos utilizar a tabela de sistema sysindexes. Existe a contagem de linhas armazenadas na tabela sysindexes. Sendo assim poderemos facilmente substituir o SELECT COUNT(*) por uma busca tabela de sistema, a sysindexes. Como segue:
select rows from sysindexes where object_name(id) = 'tmp_apl_vida' and indid = 1 -- Se existir ndice cluster (normal em PK) pode pegar o total de linhas assim

Poderemos aumentar a performance com essa substituio. Ou ainda, existe a opo de recebermos o total de linhas processadas logo aps o comando.
Declare @linhas as int select id_origem, cd_regra from rgr_mod_geral where ID_ORIGEM=54100001 Set @linhas = @@rowcount

Como nada to ruim que no possa ser piorado, temos um Best Seller no assunto. Reconstituio de caso de mal uso de verificao de existncia de dados:
DBCC DROPCLEANBUFFERS SET STATISTICS IO ON declare @QtdeRegistros as int

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Select @QtdeRegistros = count(*) from apl_certificado if @QtdeRegistros > 0 select 'Existe' -->Table 'APL_CERTIFICADO'. Scan count 1, logical reads 1902, physical reads 3, read-ahead reads 1904.

Facilmente contornamos isso:


DBCC DROPCLEANBUFFERS if exists(select 1 from apl_certificado) select 'Existe' -->Table 'APL_CERTIFICADO'. Scan count 1, logical reads 3, physical reads 3, read-ahead reads 0.

HAVING E GROUP BY versus WHERE


Relevncia: Alta Tentar evitar o uso da clusula HAVING sempre que possvel. Clusula HAVING usada pra restringir os resultados retornados pela clusula GROUP BY. Quando se usa HAVING com o GROUP BY as linhas so divididas em grupos de resultados, agregando seus valores. Ento a clusula HAVING elimina grupos agregados indesejados. Muitas vezes possvel substituir o HAVING por WHERE. Isso pode aumentar a performance da query em diversas vezes. Para potencializar a melhor forma de utilizao da clusula WHERE, ou justificar o uso, tenha em mente o seguinte: - Ao menos um dos filtros deve ter alta seletividade de registros - Se um ou mais filtros no for de alta seletividade, considere a criao de um ndice. - Se nenhuma das condies de filtro possuir alta seletividade considere a criao de um covering index

Ordenar dados - GROUP BY versus ORDER BY


Relevncia: Baixa O GROUP BY no ordena o resultado de dados. Esse comportamento existia em verses anteriores verso 7.0. Nessa poca no existia paralelismo de processos distribudos em processadores, portanto a clusula GROUP BY j ordenava o conjunto de dados. Atualmente os servidores so multi-processados e, portanto a carga de trabalho dividida e empacotada medida que atendida, resultando em desordem de dados. Se houver a necessidade de ordenao utilize o comando ORDER BY.

Cursores
Relevncia: Mdia Devem ser evitados no SQL Server. A performance de processamento linha-a-linha inferior a comandos em lote. Utilize-os apenas aps esgotar todas as possibilidades de montagem dos comandos.

Cursores versus Variveis tipo Tabela


Relevncia: Mdia Tentar enviar o uso de cursores SQL Server sempre que possvel. O cursor mais lento e degrada performance. D preferncia para uso de variveis do tipo tabela ou, melhor ainda, tente utilizar subquery (operador IN, por exemplo).
declare @vartab TABLE (classId varchar(40))

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
insert into @vartab select class_id from tbg_usuario_logado where cd_usuario = @cdUsuario and class_id = @ClassId delete from rgr_tmp_escalonavel where class_id in (select ClassId from @vartab)

Processo feito em memria e requer menos lock do que cursores ou #temporrias.

SET
Relevncia: Alta No utilize de configuraes locais para Procedimento Armazenado ou Vises. Alguns comandos SET mudam caractersticas da sesso, afetando tambm o comportamento de execuo do objeto. O resultado disso a recompilao do objeto a cada execuo em que submetido. Apesar de uma recompilao ser quase imediata, considere que possam existir vrios usurios executando o mesmo procedimento e s ser atendido aps cada execuo do mesmo ser encerrada e chegar sua vez de recompilar. E assim ser sucessivamente at que todos os pedidos sejam atendidos. Se houver a necessidade que algum SET seja utilizado, deve ser revisto com o administrador sobre a possibilidade de padronizar essa configurao diretamente na configurao default do servidor de banco de dados. Lista de SET que podem causar recompilao nas Procedures:
DATEFORMAT ANSI_DEFAULTS ANSI_NULL_DFLT_OFF ANSI_NULL_DFLT_ON ANSI_NULLS ANSI_PADDING CONCAT_NULL_YIELDS_NULL FORCEPLAN ANSI_WARNINGS ARITHABORT LANGUAGE NUMERIC_ROUNDABORT QUOTED_IDENTIFIER

Lista de SET que NO causam recompilao nas Procedures: (Se necessrio devem ser usados com cautela e conhecimento)
ARITHIGNORE CURSOR_CLOSE_ON_COMMIT DEADLOCK_PRIORITY FMTONLY IDENTITY_INSERT IMPLICIT_TRANSACTIONS LOCK_TIMEOUT NOCOUNT NOEXEC PARSEONLY QUERY_GOVERNOR_COST_LIMIT ROWCOUNT STATISTICS IO STATISTICS TIME TRANSACTION ISOLATION LEVEL XACT_ABORT

Questo: Com o uso das boas prticas as recompilaes e serializaes cessaro?


14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
A resposta NO. Por qu? Por que o SQL 2000 tem condies determinantes que indicam o momento, dentro de um cenrio especfico, seja alterao de um volume grande de dados ou alterao de estrutura durante a execuo de um Procedimento Armazenado. Veja na seo Tabelas Temporrias.

Transaes / @@TRANCOUNT
Relevncia: Alta Cuidado com transaes precipitadas. Somente inicie a transao no ponto exatamente antes de incio de manuteno dos dados de tabelas de negcio. A transao pontual e ser acionada no momento que o passo interno da procedure alcance sua posio. Portanto, para carregar dados em temporrias, executar funes ou selects para resgatar qualquer informao, no abra transao. Transacione somente quando estiver com tudo em mos. Dados temporrios no so transacionados. - Ao entrar em rotina de erro, antes de efetuar o ROLLBACK, fazer teste da possvel existncia da transao.
/*Exemplo*/ Begin Comandos fora da transao que tambm podero causar erros If @@error > 0 goto trataerro Begin transaction Comandos que precisam ser transacionados If @@error > 0 goto trataerro Commit transaction Trataerro: If @@trancount > 0 rollback

...
End

Importante: No utilize transaes diretamente no cdigo da aplicao se o tipo do banco de dados for o mesmo em todas as conexes. O recurso de transaes disponveis nos drivers utilizados pela aplicao (ADO, RDO, DAO) tem como finalidade facilitar a transao entre bancos de dados de fornecedores diferentes. Exemplo: Uma determinada transao no servidor ORACLE depende de recursos processados no servidor SQL e somente pode ser dado como concludo se ambos obtiverem sucesso. Se esse no for o cenrio, deixe que o servidor de banco de dados cuide das transaes. Evite transaes presas porque esqueceu de encerr-las, ou porque um MSGBOX foi apresentado ao usurio e ele no deu um clique no boto para o processo seguir em tempo hbil. Ou ainda, evite que o tempo gasto entre a montagem de tela, a espera pelo recebimento de dados do servidor, consumam tempo prendendo os recursos de uma transao feita na aplicao que aguardou por essas atividades desnecessrias para o processamento dos dados. Sempre faa transaes em Procedimentos Armazenados.

CONSTRAINT versus TRIGGER


Relevncia: Alta Sempre que possvel utilizar constraints ao invs de triggers. Constraints so muito mais eficientes que triggers e podem impulsionar a performance.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

COVERING INDEX e VIEW Indexada


Relevncia: Baixa COVERING INDEX so ndices que possuem 2 ou mais colunas e tem finalidade especfica: Atender a uma demanda acima do normal de um determinado statement, comumente usado. Quando repetidamente usamos uma situao de COUNT, SUM, AVG, etc, podemos estudar a criao de um COVERING INDEX. Considere um cenrio bem tpico: (temos a tabela ORDERS com um clustered index na coluna CUSTOMER_ID) 1) Analisando o Plano de execuo:
set showplan_text on go select orderdate, sum(Freight) as Freight from NorthWind.dbo.orders group by orderdate
|--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL else [Expr1008])) |--Stream Aggregate(GROUP BY:([Orders].[OrderDate]) DEFINE:([Expr1007]=COUNT_BIG([Orders].[Freight]), [Expr1008]=SUM([Orders].[Freight]))) |--Sort(ORDER BY:([Orders].[OrderDate] ASC)) |--Clustered Index Scan(OBJECT:([Northwind].[dbo].[Orders].[PK_Orders]))

O plano de execuo dessa query bem simples. O engine do banco de dados percorre por todo o ndice clusterizado, e ento aplica o SORT intermedirio para satisfazer a clusula GROUP BY. 2) Analisando as estatsticas de leitura: Execute novamente a query:
set showplan_text off go set statistics io on go select orderdate, sum(Freight) as Freight from NorthWind.dbo.orders group by orderdate logical reads 21, physical reads 0, read-ahead reads 0.

3) Criando um covering index: Poderia um non-clustered index aumentar a velocidade desta query? Afirmativo. Basta criarmos um non-clustered index contendo todas as colunas utilizadas na query:
CREATE INDEX order_amt ON NorthWind.dbo.ORDERS(ORDERDATE, FREIGHT)

Execute novamente a query:


select orderdate, sum(Freight) as Freight from NorthWind.dbo.orders group by orderdate logical reads 4, physical reads 0, read-ahead reads 0.

Execute novamente a query:


set showplan_text on go set statistics io off go select orderdate, sum(Freight) as Freight from NorthWind.dbo.orders group by orderdate
|--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL else [Expr1008])) |--Stream Aggregate(GROUP BY:([Orders].[OrderDate]) DEFINE:([Expr1007]=COUNT_BIG([Orders].[Freight]), [Expr1008]=SUM([Orders].[Freight]))) |--Index Scan(OBJECT:([Northwind].[dbo].[Orders].[order_amt]), ORDERED FORWARD)

Limpe a seo e elimine o ndice criado para esse teste:


set showplan_text off go set statistics io off go drop index NorthWind.dbo.orders.order_amt go

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

TOP n / SET ROWCOUNT n


Relevncia: Alta Sempre que possvel utilizar nos SELECTS a palavra chave TOP ou configure o comando SET ROWCOUNT n para um resultado resumido. Isso resultar em uma quantidade menor de linhas, que muitas vezes, atende perfeitamente necessidade. Isso pode reduzir o trfego entre o server e o client. Tambm reduz o consumo de recursos necessrios para a operao.

UNION versus UNION ALL


Relevncia: Baixa Tentar usar sempre o comando UNION ALL ao invs de UNION. O comando UNION ALL mais rpido que o UNION, porque o comando UNION ALL no procura por linhas duplicadas ao contrrio do UNION que sempre procura por duplicidades de linhas, se existe ou se no existe duplicidade. Para descartar as possveis duplicidades recebidas com uso do UNION ALL ser necessrio aplicar posteriormente a clusula DISTINCT. Nesse caso necessrio o uso do DISTINCT, pois mais eficiente remover duplicidades assim do que com o uso do UNION que precisa ligar duas ou mais tabelas e tratar das duplicidades em ambas enquanto seleciona as linhas. Mesmo assim utilize o DISTINCT com cautela, pois para o SQL eliminar as duplicidades com esse comando necessrio um processamento extra no plano de execuo, bem como na ao efetiva.

HINT de ndices (INDEX=XXXX)


Relevncia: Baixa No use hints de ndices na otimizao nas querys. (INDEX=XXX) O SQL Query Optmizer inteligente, ele sabe o que, e como deve ser usado e praticamente impossvel de ser superado. mais confivel, interferir poder ferir o desempenho. Outro ponto importante que muitas vezes no temos em definitivo o nome dos ndices que criamos. Em ambiente de produo o Cliente pode adotar padres ou optar por no criar determinado ndice. Nesses casos nosso cdigo conter erro e no ser compilado.

HINT de modo de leitura (NOLOCK)


Relevncia: Mdia Em consultas e relatrios cabe analisar a possibilidade de uso de HINT de modo de leitura. O HINT de leitura suja, NOLOCK serve para no aguardar transaes pendentes serem encerradas para iniciar a leitura. Porm seu uso deve ser cauteloso. Leitura suja apresenta informaes ainda no conclusivas. Esses dados podem se modificar at que se consolide ou aborte a transao.

COALESCE e ISNULL versus CASE WHEN


Relevncia: Mxima Seja prudente e teste a performance quando utilizar as funes COALESCE e ISNULL. Em alguns casos o CASE evita leitura adicional de dados. As funes COALESCE e ISNULL requerem muito recurso para processar, dificultando o acesso ao plano de execuo e ndice correto.
select endo.id_endosso, (case when rgr.id_origem is not null then 1 else 0 end) as eh_regra_318 from apl_contrato as CONT inner join tbg_empresa as EMP on emp.cd_empresa = cont.cd_empresa inner join tbg_sucursal as SUC on suc.cd_empresa = cont.cd_empresa and suc.cd_sucursal = cont.cd_sucursal

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
inner inner inner inner zero inner and and inner left where and and and and join join join join tbg_ramo as RAM on ram.cd_rm = cont.cd_rm apl_subestipulante as SUB on sub.id_contrato = cont.id_contrato apl_subestipulante_plano as SUBP on subp.id_subestipulante = sub.id_subestipulante apl_certificado as CER on cer.id_subestipulante = sub.id_subestipulante and cer.nro_certificado = 0 --

join apl_endosso as ENDO on endo.id_subestipulante = sub.id_subestipulante endo.tp_endosso = '11' -- cobrana endo.dt_cancelamento = '40001231' join cbr_cobranca as COB on cob.id_cobranca = endo.id_cobranca join rgr_mod_geral as RGR on rgr.id_origem = cer.id_origem and rgr.cd_modulo = 'MDAE' and rgr.cd_regra sub.idc_status = 'a' -- ativos cont.cd_empresa = @cd_empresa cont.cd_sucursal = @cd_sucursal cont.cd_rm = @cd_rm cont.nro_apolice = @nro_apolice

= 318

Parmetros so exigidos, portanto fazer a comparao diretamente


select endo.id_endosso, (case when rgr.id_origem is not null then 1 else 0 end) as eh_regra_318, endo.id_subestipulante, endo.id_origem, ENDO.dt_inicio_vigencia from apl_contrato as CONT inner join tbg_empresa as EMP on emp.cd_empresa = cont.cd_empresa inner join tbg_sucursal as SUC on suc.cd_empresa = cont.cd_empresa and suc.cd_sucursal = cont.cd_sucursal inner join tbg_ramo as RAM on ram.cd_rm = cont.cd_rm inner join apl_subestipulante as SUB on sub.id_contrato = cont.id_contrato inner join apl_subestipulante_plano as SUBP on subp.id_subestipulante = sub.id_subestipulante inner join apl_certificado as CER on cer.id_subestipulante = sub.id_subestipulante and cer.nro_certificado = 0 -zero inner join apl_endosso as ENDO on endo.id_subestipulante = sub.id_subestipulante and endo.tp_endosso = '11' -- cobrana and endo.dt_cancelamento = '40001231' inner join cbr_cobranca as COB on cob.id_cobranca = endo.id_cobranca left join rgr_mod_geral as RGR on rgr.id_origem = cer.id_origem and rgr.cd_modulo = 'MDAE' and rgr.cd_regra = 318 where sub.idc_status = 'a' ativos3 and @cd_empresa is null or ( cont.cd_empresa = (case when @cd_empresa is not null then @cd_empresa else cont.cd_empresa end)) and @cd_sucursal is null or ( cont.cd_sucursal = (case when @cd_sucursal is not null then @cd_sucursal else cont.cd_sucursal end)) and @cd_rm is null or ( cont.cd_rm = (case when @cd_rm is not null then @cd_rm else cont.cd_rm end)) and @nro_apolice is null or ( cont.nro_apolice = (case when @nro_apolice is not null then @nro_apolice else cont.nro_apolice end)) and @NM_RM is null or ( ram.nm_rm like (case when @NM_RM is not null then @NM_RM + '%' else ram.nm_rm end))

Uso de CASE. Todos os parmetros so opcionais e precisam ser tratados.

Evidncia:

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 1: Execuo com ISNULL e LIKE % - degradao.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 2: Uso correto de tratamento de nulidade de varivel com CASE WHEN. Boa performance.

Uso incorreto: (ces.nm_estipulante like ISNULL(@nmestipulante, ces.nm_estipulante) + '%') - A varivel @nmestipulante nula e ento o filtro sobre o campo da tabela mais o smbolo %. Em ambos os casos o smbolo % aplicado. Correto: O ponto forte dessa tcnica aplicar o smbolo % somente quando a condio for verdadeira. Com CASE WHEN (@nmestipulante is null or ces.nm_estipulante = (case when @nmestipulante is not null then @nmestipulante + % else ces.nm_estipulante end )) temos o descarte imediato, quando inicialmente fazemos o tratamento de nulidade na varivel (@nmestipulante is null) e logo em seguida fazemos o tratamento. Com ISNULL (ces.nm_estipulante like ISNULL(@nmestipulante + '%', ces.nm_estipulante)) essa condio tambm funcionar bem, porm depende do resultado da concatenao (@nmestipulante + '%') resultar em NULL. Pois dependendo da configurao do banco esse resultado ser '%' e o filtro ter um comportamento diferente. Para que a concatenao entre campo com valor + NULL no retorne NULL, utilize:
set concat_null_yields_null off declare @var varchar(20) set @var = 'TEXTO' select @var + null

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
-------------------TEXTO (1 row(s) affected) Figura 1: Resultado de concatenao com NULL.

Lembre-se que a configurao SET concat_null_yields_null causa recompilao do objeto. Veja na seo SET a lista completa

Tabelas temporrias
Relevncia: Alta Tentar conter o uso excessivo de tabelas temporrias. As tabelas temporrias so criadas no banco de dados compartilhado (tempdb) que por sua vez armazena os locks, cursores e muitos outros recursos em andamento dos processos do banco de dados em geral. Sendo assim, a criao de uma simples tabela temporria pode demorar muito devido ao consumo do tempdb ser elevado. Para os testes de performance, normalmente, usamos um servidor com instncia de pouca concorrncia para medio de tempo e ganho. Ocorre que o ganho aparentemente obtido com o uso de temporria pode se transformar em total degradao num ambiente de alta concorrncia. Usar com moderao. O uso de ndices em #temporrias pode ser adotado com moderao, porm observe o seguinte:
/* Exemplo 1 - Boa prtica */ CREATE TABLE #temp1 (ColA INT NOT NULL) CREATE UNIQUE INDEX MyIndex ON #temp1(ColA) INSERT INTO #temp1 SELECT IntCol FROM SomeTable GO /* Exemplo 2 - Boa prtica */ CREATE TABLE #temp1 (ColA INT UNIQUE NOT NULL) INSERT INTO #temp1 SELECT IntCol FROM SomeTable /* Exemplo 3 - No faa assim */ CREATE TABLE #temp1 (ColA INT NOT NULL) INSERT INTO #temp1 SELECT IntCol FROM SomeTable CREATE UNIQUE INDEX MyIndex ON #temp1(ColA) GO

Cada vez que um comando DDL (create, drop, alter) executado em uma tabela temporria todos os grupos que referenciam a ela sero recompilados. Nos exemplos 1 e 2 a tabela ainda no est populada, portanto o momento exato para criar os ndices. E o query optimizer garante que o comando CREATE ser executado apenas uma vez. Se o ndice for criado aps a tabela conter dados o objeto ser refeito na memria, consumindo mais recursos. - A boa prtica recomenda criar as temporrias no topo do Procedimento Armazenado. - Quando houver a necessidade de criar temporria que outros Procedimentos utilizaro no decorrer da execuo (NESTED ou aninhamento), verifique a possibilidade de criar a temporria no prprio Procedimento que ir utilizar. Ou se possvel, substitua temporria por varivel do tipo tabela. Exemplo de mal uso de preenchimento de temporria:
create procedure Up_Teste as create table #tmp (id_teste integer) exec up_Teste2 select id_teste from #tmp

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
go create procedure Up_Teste2 as insert into #tmp (id_teste) select id_Teste from tabela go

No caso acima o Procedimento Armazenado inicial up_teste cria uma temporria e quem abastece com dados outro Procedimento Armazenado, a up_teste2. Essa prtica faz com que os objetos sejam recompilados toda vez que forem executados. Procure abastecer a tabela temporria dentro do mesmo objeto que a criou. Veja os casos em que sempre ocorrer recompilao, no dependendo da boa prtica aplicada: -Mudanas de Esquema: Ao criar, alterar ou remover um ndice. (Aps populao da tabela, incluindo as temporrias). -Alterao de linhas: Ao manipular um volume de linhas em uma tabela. O nmero de gatilho depende do tipo de objeto. Tabela de recompilao de acordo com Qtde de registros em temporrias:
Gatilho Tipo de Tabela Permanente Temporria Varivel tipo Table Tabela Vazia < 500 linhas < 6 linhas No se aplica No Recompila >= 500 >= 6 linhas No se aplica Tabela Populada >= 500 + (20% de cardinalidade) >= 500 + (20% de cardinalidade) No se aplica

Recompila Quando

Controvrsia: Porm em nosso dia-a-dia ocorrem situaes em que menos oneroso adaptar a temporria aps a sua criao do que utilizar de CONVERT e CAST por todo o resto do procedimento. Tempos o exemplo de uma determinada procedure de carga de dados em que todas as linhas a serem processadas se encontram em uma tabela (tmp_importacao). Linha a linha, de acordo com a estrutura do arquivo (.TXT) de origem. No caso foi vantajoso usar uma soluo que fere as boas prticas, pois o arquivo de origem continha 110 mil linhas e conta com um passo primrio de crtica de dados. Soluo adotada para esse caso: - Criar uma temporria com as diversas colunas necessrias. Todas do tipo VARCHAR(255), - Abastecer as colunas da temporria com base no TXT, - Testar as colunas (considerando datatypes), criticar e remover as linhas inconsistentes, - Alterar o tamanho e o tipo das colunas da temporria para enquadrar no perfil das tabelas finais do negcio, - Criar os ndices necessrios. Nesse caso o ganho foi de 8 horas. Controvrsia 2: A recomendao da Microsoft : No utilizar SELECT INTO #, devemos primeiramente criar a estrutura da temporria e depois preench-la com INSERT INTO. Porm, em casos em que o volume de informao temporria grande a degradao se potencializa de forma absurda. Recentemente desmistificamos essa recomendao com as rotinas de UP_APL_ObterCapitalTecnico.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Nesse caso o ganho foi de 2 horas, pelo menos. A rotina foi interrompida aps 2 horas de execuo sem concluir. Com o ajuste passou a executar em 15 minutos.

Dica geral para a adoo de criao de tabelas temporrias: Analise primeiramente a quantidade de registros que sero armazenados, e em caso de grandes volumes, opte por SELECT INTO#. Em casos de poucos registros aceitvel a criao previamente da estrutura para ento preench-la com INSERT INTO.

Seqncia / Auto-numerao
Na verso 2000 do SQL NO existe como auto-numerar atravs de um SELECT em conjunto com INSERT diretamente para outra tabela a partir de um dado valor. comum encontrar situaes em que precisamos numerar um lote de registros sequencialmente e ento inserir nas tabelas do sistema a partir do ltimo nmero l existente. (Essa situao foi detectada pela Microsoft em nosso cdigo e comum) Soluo adotada: 1- Criar estrutura temporria ou varivel do tipo tabela (table variable) com a estrutura final + um campo de identificao do tipo auto-numerao. 2- Abastecer essa estrutura, 3- Eleger o maior registro da tabela destino, 4- Inserir na tabela destino os dados da temporria ou da varivel tabela e no campo de seqncia adotar o maior desse registro de identificao + o nmero auto-numerado, criado na temporria ou varivel tabela. Note que preciso abastecer uma estrutura, somente para no perder a seqncia do identificador da tabela destino. Porm essa a nica forma. Se o INSERT fosse para a mesma tabela do SELECT teramos a tcnica:
BEGIN TRANSACTION INSERT INTO CLI_SEGURADO(ID_SEGURADO, NM_SEGURADO) SELECT MaxSeg.MaxSeg + (SELECT COUNT(segnum.id_segurado) FROM cli_segurado segnum WHERE segnum.id_segurado >= seg.id_segurado ) AS CodigoNovo, --(SELECT COUNT(segnum.id_segurado) FROM cli_segurado segnum WHERE segnum.id_segurado >= seg.id_segurado ) --AS Sequencia, -- Lista sequencial dos registros LEFT(rtrim(nm_segurado) + ' -> ' + isnull(nm_ocupacao,'Desocupado'),50) AS 'nm_segurado' FROM cli_segurado seg inner join (select isnull(max(id_segurado),0) MaxSeg from cli_segurado) MaxSeg on 1=1 ORDER BY nm_segurado, CodigoNovo IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION

Procedure com Parmetro Multivalorado (uso de XML)


Relevncia: Mdia Pergunta: Quando a aplicao oferece ao usurio uma lista em que ele pode selecionar itens de 1 a n, qual a sada normalmente adotada pelo desenvolvedor? Normalmente cria-se um parmetro na procedure do tipo VARCHAR e a aplicao passa uma lista delimitada para a procedure montar as condies de filtro. Ou ento, a aplicao faz um loop e a cada volta do lao executa a procedure, passa o prximo item da lista selecionado, recebe o retorno e vai acumulando (array, etc) a cada volta do lao.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Podemos contar com o auxlio do XML para situaes como essa. Note o exemplo abaixo:
CREATE PROCEDURE UP_BuscaRegras ( @ListaDeParametros varchar(1000) ) AS BEGIN SET NOCOUNT ON DECLARE @XML int EXEC sp_xml_preparedocument @XML OUTPUT, @ListaDeParametros select vid.id_vida, prmg.cd_regra, cer.id_certificado, cer.nro_certificado from apl_vida as vid inner join apl_certificado as cer on cer.id_certificado = vid.id_certificado and cer.nro_certificado > 0 inner join rgr_mod_geral as prmg on prmg.cd_modulo = 'MDAE' and prmg.id_origem = cer.id_origem inner join rgr_dado_geral as prdg on prdg.id_dado = prmg.id_regra JOIN OPENXML (@XML, '/ROOT/Ord',1) WITH (CdRegra int) AS x ON prmg.cd_regra = x.CdRegra order by vid.id_vida, prmg.cd_regra EXEC sp_xml_removedocument @XML END GO EXEC UP_BuscaRegras '<ROOT><Ord CdRegra = "9"/> <Ord CdRegra = "124"/></ROOT>' GO id_vida -------------------4 4 10 10 13 15 15 21 25 cd_regra ----------9 124 9 124 9 9 124 9 9 id_certificado ---------------171 171 183 183 188 194 194 206 210 nro_certificado --------------2 2 3 3 1 1 1 1 1

...

Uso de XML pode ser considerado como dica. Porm, enquadra-se mais em boa conduta e fator de economia de recursos no processamento, pois evita a necessidade de funes para separar os valores delimitados em parmetros.

CONVERT / CAST / SARG


Relevncia: Alta No converter campos se no for necessrio. Antes de criar uma varivel que ser utilizada para comparao com um campo de tabela verifique o datatype do mesmo. Se precisar usar hard-code para tratar datas, siga os passos:
Declare @vdate as datetime --ou varchar(8) set @vdate = '19831231' select * from prp_segurado where dt_nascimento = @vdate

Se a converso for necessria, converter o 'lado' mais fcil, quer dizer, o lado com menos linhas e de converso mais simples. Se a comparao for com uma varivel, aplicar a converso diretamente na prpria varivel.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
/*Exemplo - No faa assim */ select id_segurado, dt_nascimento from sise_des..prp_segurado where convert(varchar(10), dt_nascimento, 103) = '31/12/1982' /*Exemplo - Boa prtica */ select id_segurado, dt_nascimento from sise_des..prp_segurado where dt_nascimento = '19821231'

O Hard-Code '19821231' funciona perfeitamente por se enquadrar no formato 112 do CONVERT de datas. E isso independe de qualquer configurao aplicada nas Configuraes Regionais.

SARG Ao fazer converso em colunas de query siga algumas dicas de SARG. SARG representa funes em comandos WHERE que possuem um valor constante para a comparao. O tipo de funo aplicada a uma coluna na condio WHERE determina se a condio SARG ou no. Exemplo 1: O comando No SARG
WHERE SUBSTRING(PrimeiroNome,1, 1) = m

pode ser reescrito assim para tornar-se SARG


WHERE PrimeiroNome Like m%

Ambos os casos produzem o mesmo resultado. Porm o primeiro caso um exemplo de No SARG e ser mais lento, enquanto que o segundo caso classificado de SARG e, portanto ser muito mais rpido e poder ainda tirar proveito de possveis ndices existentes nessa coluna. Exemplo 2:
-- Criar um indice na PRP_SEGURADO. (SOMENTE PARA APRESENTAO DESSA PRTICA) create index idx_lixo_prp_segurado on prp_segurado (dt_Nascimento) -- Testar uso do ndice. select id_segurado, nm_segurado, dt_nascimento from prp_segurado where dt_Nascimento = '19730224'

Figura 1: Resultado da execuo direta do filtro para certificarmos se o ndice executado corretamente. --Buscar segurados com idade maior que 21 anos select max(dt_nascimento)

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
from prp_segurado where datediff(yy, dt_Nascimento, getdate()) > 21

Figura 2: Resultado da execuo com uso de funo Non-SARG. ndice usado, porm utilizou varredura (SCAN) --Buscar segurados com idade maior que 21 anos select max(dt_nascimento) from prp_segurado where dt_Nascimento < dateadd(yy, -21, getdate())

Figura 3: Resultado da execuo com uso de funo SARG. Perfeito, INDEX SEEK. drop index idx_lixo_prp_segurado.prp_segurado

Exemplo 3: Ao invs de:


WHERE NOT Codigo > 5

Prefira:
WHERE Codigo <= 5

Ambos tm a mesma finalidade, porm o segundo caso um SARG e usar ndice (quando existir). Quando no souber qual condio SARG use o Query Plan do Query Analyzer. Com algum cuidado, e com um pensamento inteligente, muitas No SARG podem ser adaptadas para tornarem-se SARG. Em view indexada a converso entre datatypes restrita e deve ser contornada ou evitada.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

No prximo exemplo podemos ver algo comum, o tratamento de data que recomendamos na seo CONVERT / CAST / SARG no se aplica aqui. Exemplo 4: (Soluo para uso em View Indexada) Ao invs de:
and dt_cancelamento = '40001231'

Prefira:
and dt_cancelamento = dateadd(d, 1, '40001230')

Note que o comando DATEADD um SARG, CONVERT e CAST no so. Com um pequeno jogo de cintura possvel contornar essa situao. No exemplo anterior foi utilizado o comando DATEADD para uma string e adicionado um dia. O resultado desse SARG um DATETIME e portanto chegamos ao resultado que queramos. Se existisse um ndice na coluna dt_cancelamento ou se essa condio fosse utilizada numa query indexada seria vlida e o ndice seria aproveitado perfeitamente.

NOT IN, IN, EXISTS e NOT EXISTS


Relevncia: Mdia Procure evitar o uso de NOT IN. Ele degrada a performance e comumente utiliza Table Scan para executar esse comando. D preferncia ao uso de: - EXISTS ou NOT EXISTS - IN (porm a ferramenta MDA desaconselha o uso tente utilizar EXISTS ou BETWEEN) - LEFT JOIN e feche a nulidade das condies

IN versus OR
Relevncia: Baixa O operador de restrio IN deve ser evitado na medida do possvel. A ferramenta de avaliao do Cliente FMDA no aprova o uso. Tente usar o operador OR ou a condio EXISTS ou BETWEEN. Exemplo:
/*Exemplo - no faa assim*/ select id_origem, cd_regra from rgr_mod_geral where cd_regra in (38, 296) /*Exemplo sugerido como correto*/ select id_origem, cd_regra from rgr_mod_geral where cd_regra = 38 or cd_regra = 296

Apesar de parecer lusitano devemos adotar essa prtica.

FRAGMENTAO DE OBJETO
Relevncia: Alta Fragmentar um objeto significa dividi-lo em mais partes. E mdia, um objeto passvel de ser fragmentado quando possuir mais que 300 linhas.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

O SQL degrada e "cansa" no momento em que varre um plano de execuo muito extenso. Sugiro criar parties da mesma, como a seguir: UP_MAS_OBTEMPROPOSTAS -- ( o objeto que continha todo o cdigo e passa a ser a master) UP_MAS_OBTEMPROPOSTAS_P1 -- ( uma parte da original, mas voltada somente para APL) UP_MAS_OBTEMPROPOSTAS_P2 -- ( uma parte da original, mas voltada somente para PRP)

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Dicas Gerais
Criao de Vises ou Funes para comportar regras de negcio Nos projetos em geral, mais especificamente no SISE, comum encontrar duplicidade de regras de negcio espalhadas pelas procedures. Cito aqui o exemplo de rotina para resgatar dados bancrios. Os dados bancrios de massificados pertencem regra 140. A sigla de classificao do mdulo do massificados MAS. As informaes bancrias ficam na estrutura da MOD_GERAL e DADOS_GERAL. Sempre que necessrio resgatar essas informaes os analistas fazem a ligao (LEFT JOIN) com essas tabelas, aplicam o filtro (WHERE) de mdulo e regra para, ento, resgatar os dados. Malefcios (sem views): - Duplicidade de cdigo (redundncia) - Dificlima Manuteno - Requer conhecimento apurado do negcio para saber quais regras aplicar. - Hard-code espalhado e visvel para todo crtico ver (pssima prtica) Benefcios (com views): - Encapsulamento de cdigo. - Manuteno rpida e barata - No requer conhecimento do negcio para uso da view - Cdigo mais limpo - Performance. Acesso mais rpido se a view for indexada Ocorre que, alm da visvel duplicidade de cdigo, essa uma prtica conhecida como Cdigo Redundante. Quando existe a necessidade de manuteno nessa regra os analistas precisam caar todos os pontos em que esse cdigo aparece e fazer a alterao e ento testar toda a aplicao novamente. Nem preciso dizer que o risco de cometermos erros durante essa manuteno enorme, exigindo, muitas vezes, unio de esforos da equipe para fazer tal manuteno. Sempre que ocorrer a necessidade de filtrar uma determinada situao com hard code analise a possibilidade de criao de view indexada. Veja o exemplo abaixo: Cdigo resumido da procedure que busca dados bancrios (verso atual):
Select distinct top 200 'Apl' As TpRegistro, cer.id_certificado, dad.nm_dado01 as CdBanco, dad.nm_dado02 as CdAgencia, dad.nm_dado03 as CdContaCorrente, cer.nro_proposta as NroPropostaEst From Prd_Plano Pla inner join Apl_Certificado Cer On Cer.Cd_Produto = Pla.Cd_Produto and Cer.Cd_Plano = Pla.Cd_Plano Left Join Rgr_Mod_Geral Mod On Mod.Id_origem = cer.id_Origem and Mod.Cd_Modulo = 'MAS' and Mod.Cd_Regra = 140 Left Join Rgr_Dado_Geral Dad On Dad.Id_Dado = mod.id_regra

Criao da View e de ndice:


SET NUMERIC_ROUNDABORT OFF GO SET ANSI_PADDING,ANSI_WARNINGS,CONCAT_NULL_YIELDS_NULL,ARITHABORT,QUOTED_IDENTIFIER,ANSI_NULLS ON GO

*Esses SETs so obrigatrios na sesso em que a view ser criada. Exigncia do SQL.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

create view vw_MAS_DadosBancarios with schemabinding as select Mod.Id_origem, dad.nm_dado01, dad.nm_dado02, dad.nm_dado03 from dbo.Rgr_Mod_Geral Mod inner Join dbo.Rgr_Dado_Geral Dad On Dad.Id_Dado = mod.id_regra where Mod.Cd_Modulo = 'MAS' and Mod.Cd_Regra = 140 go CREATE UNIQUE CLUSTERED INDEX idx_vw_MAS_DadosBancarios_01 on vw_MAS_DadosBancarios (Id_origem)

Correo do cdigo parcial da procedure que busca dados bancrios (verso com uso da nova view):
Select distinct top 200 'Apl' As TpRegistro, cer.id_certificado, dad.nm_dado01 as CdBanco, dad.nm_dado02 as CdAgencia, dad.nm_dado03 as CdContaCorrente, cer.nro_proposta as NroPropostaEst From Prd_Plano Pla inner join Apl_Certificado Cer On Cer.Cd_Produto = Pla.Cd_Produto and Cer.Cd_Plano = Pla.Cd_Plano left join vw_DadosBancarios as dad on dad.Id_origem = cer.id_Origem

As views indexadas tambm podem melhorar a performance de uma query. Para isso acontecer a view precisa ser a mandatria ou a tabela guia da query e principalmente precisa ser escrita de forma que reduza os registros ao mximo com clusulas de filtro (WHERE). Ao adotar o uso de view para busca de condies especficas como essa de dados bancrios, devemos considerar: - Views so estruturas tratadas como tabelas e devem fazer parte do modelo de dados - Views indexadas ocupam espao fsico no banco de dados - Existe limitao no uso de comandos. Somente so aceitos os comandos deterministas (Veja requisitos) Requisitos para criao de views indexadas necessrio que a seo em que ira criar a view esteja setada com os comandos na seguinte forma:
SET NUMERIC_ROUNDABORT OFF GO SET ANSI_PADDING,ANSI_WARNINGS,CONCAT_NULL_YIELDS_NULL,ARITHABORT,QUOTED_IDENTIFIER,ANSI_NULLS ON GO

A view dever conter as palavras WITH SCHEMABINDING logo aps o nome da mesma na declarao. As tabelas utilizadas na view devem ser procedidas pelo seu owner (dono).
dbo.Rgr_Mod_Geral

O comando SELECT definido na view indexada no pode conter: - As palavras-chave TOP, DISTINCT, COMPUTE, HAVING, UNION, COUNT, - Subquery, - Tabelas com asterisco (*), - Lista de SELECT no pode conter expresses, - No pode conter funes de uma agregao (GROUP BY). Exceto SUM e COUNT_BIG(*). Outros (MIN, MAX, ) no so suportados. - Os campos na lista do SELECT no podem ser do tipo FLOAT. Esse datatype do tipo nonprecise (impreciso). Para saber se um determinado campo do preciso, utilize:
drop table TestePrecisao go create table TestePrecisao

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
( tpFloat tpNumeric tpNumericDec tpVarchar tpInteger tpReal tpMoney ) SELECT COLUMNPROPERTY( 24 -> nonprecise SELECT COLUMNPROPERTY( 10 -> precise SELECT COLUMNPROPERTY( 10 -> precise SELECT COLUMNPROPERTY( 5 -> precise SELECT COLUMNPROPERTY( 10 -> precise SELECT COLUMNPROPERTY( 24 -> precise SELECT COLUMNPROPERTY( 19 -> precise OBJECT_ID('TestePrecisao'), 'tpFloat', 'PRECISION') OBJECT_ID('TestePrecisao'), 'tpNumeric', 'PRECISION') OBJECT_ID('TestePrecisao'), 'tpNumericDec', 'PRECISION') OBJECT_ID('TestePrecisao'), 'tpVarchar', 'PRECISION') OBJECT_ID('TestePrecisao'), 'tpInteger', 'PRECISION') OBJECT_ID('TestePrecisao'), 'tpReal', 'PRECISION') OBJECT_ID('TestePrecisao'), 'tpMoney', 'PRECISION') float(10), numeric(10), numeric(10,2), varchar(5), integer, real, money

A definio de uma view indexada precisa ser do tipo determinista. A view determinista se todas as expresses na lista de SELECT, bem como WHERE e GROUP BY forem deterministas. Todas as funes do SQL Server ou so marcadas como deterministic ou como non-deterministic. Uma funo deterministic se ela sempre retorna o mesmo valor se for chamada com os mesmos valores nos parmetros. Por exemplo, a funo do SQL Server DATEADD deterministic porque ela sempre retorna o mesmo resultado para cada conjunto de valores informados para os seus trs argumentos. J a funo GETDATE non-deterministic porque, sempre que invocada com o mesmo argumento, muda o valor retornado cada vez que executada. As seguintes funes nativas do SQL Server so sempre deterministic (Podem ser utilizadas):
ABS ACOS ASIN ATAN ATN2 CEILING COALESCE COS COT DATALENGTH DATEADD DATEDIFF DAY DEGREES EXP FLOOR ISNULL ISNUMERIC LOG LOG10 MONTH NULLIF PARSENAME POWER RADIANS ROUND SIGN SIN SQUARE SQRT TAN YEAR

As funes abaixo NO so sempre deterministic, porm podem ser usadas em views indexadas em colunas computadas quando utilizadas de maneira non-deterministic. Function
CAST CONVERT

Comentrio Determinista, a menos que usada com datetime, smalldatetime, ou sql_variant. Determinista, a menos que usada com datetime, smalldatetime, or sql_variant. Os tipos de
Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

14/10/2008 - 22:36

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
dados datetime e smalldatetime so deterministic se o tipo do parmetro especificado tambm for.
CHECKSUM ISDATE

Determinista, com exceo de CHECKSUM(*). Determinista somente se usada com a funo CONVERT, o estilo do parmetro de CONVERT deve ser especificado e os estilo no devem ser igual a 0, 100, 9, ou 109. Determinista somente quando um parmetro especificado.

RAND

Todas as funes de configuraes e de estatsticas do sistema so non-deterministic. Para uma lista completa dessas funes veja Configuration Functions, Cursor Functions, Meta Data Functions, Security Functions, e System Statistical Functions. Grupo de funes que so sempre non-deterministic:
@@ERROR @@IDENTITY @@ROWCOUNT @@TRANCOUNT APP_NAME CHARINDEX CURRENT_TIMESTAMP CURRENT_USER DATENAME FORMATMESSAGE GETANSINULL GETDATE GetUTCDate HOST_ID HOST_NAME IDENT_INCR IDENT_SEED IDENTITY NEWID PATINDEX PERMISSIONS SESSION_USER STATS_DATE SYSTEM_USER TEXTPTR TEXTVALID USER_NAME

Requisito Administrativo O nvel de compatibilidade do banco de dados precisa estar abaixo de 80. Um banco de dados contendo uma view indexada no poder ter seu nvel de compatibilidade alterado para menos que 80.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Plano de Execuo - Fundamentos:


Primeiramente precisamos acionar a ferramenta do Query Analyzer. Para isso basta escrever a query e teclar CTRL+L ou clicar no boto "Display Estimated Execution Plan" na barra de ferramentas do Query Analyzer. importante observar que, uma vez que os problemas de performance podem ter vrias razes e, consequentemente, vrias solues, os pontos destacados aqui so pontos bsicos que devemos analisar e na medida do possvel evitar que aconteam. Pr-requisitos antes de cada execuo (Importante) Para garantir que recursos em memria do SQL no sejam reaproveitados e favorea determinadas situaes devemos executar alguns comandos antes de iniciar cada medio. Os comandos DBCC FREEPROCCACHE e DBCC DROPCLEANBUFFERS respectivamente retiram do cache as procedures e limpa o cache de dados do SQL. Para executar qualquer comando DBCC necessrio que o usurio tenha o perfil de administrador. Primeiro Ponto: Operaes com alto percentual de consumo Em uma query simples, inicie procurando por operaes que geram um alto percentual de consumo. Procurar por operaes de alto consumo permitir que voc priorize qual problema dever ser atacado primeiro.

Se voc esta analisando uma query com mltiplos statements, ser gerado um plano de execuo separado para cada statement. Para cada plano de execuo ser mostrada a ordem de execuo da query, por exemplo: Query 1, Query 2 e seu respectivo custo. Neste caso, procure pelas queries com maior custo.

Lembre-se : O plano de execuo sempre deve ser lido da direita para a esquerda e de cima para baixo !! Segundo ponto: Table Scan, Index Scans e Clustered Index Scans

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Table Scans, Index Scans e Clustered Index Scans so operaes que navegam por todas as linhas da tabela ou do ndice e retornam as linhas que satisfazem clusula WHERE (assumindo que voc use uma clusula WHERE). Um Table Scan obtm linhas de uma tabela no indexada, conhecida tambm como heap table. Um Index Scan procura por linhas no ndice no cluster, enquanto que um clustered index scan procura por linhas no ndice cluster de uma tabela. importante destacar que os Scans nem sempre so ruins, principalmente quando em tabelas com um pequeno nmero de registros ou consultas que devem retornar todos os registros de uma tabela. Scans podem ser ruins se sua consulta roda por um perodo muito longo vindo a prejudicar inclusive outras conexes, causando o que chamamos de blocks. Os Scans so em sua maioria resolvidos atravs da criao de ndices apropriados. Algumas solues incluem alterar as consultas de forma a ser mais seletiva, ou seja, usar a clusula WHERE para filtrar ao mximo possvel os registros retornados, adicionar/remover e modificar ndices, remover hints, alterar o desing da tabela e usar a ferramenta Index Tuning Wizard para lhe auxiliar na criao de possveis ndices. Terceiro ponto: Warnings

Warnings ou alertas normalmente so vistos quando no existem estatsticas para colunas de uma tabela e essas colunas so utilizadas como filtros de pesquisa nas queries. Eles podem ser solucionados atravs da criao de estatsticas para a coluna afetada (CREATE STATISTICS) ou ainda, criao de ndices e adio de clusulas JOIN. Quarto ponto: Seta muito grossa

As setas no so operadores, elas simplesmente so usadas para ligar um operador a outro. Atravs das setas podemos ter uma estimativa da quantidade de linhas afetadas por uma query, isto porque, quanto maior a espessura da seta, maior a quantidade de linhas envolvidas na operao. Ou se preferir, a quantidade de linhas passada de um operador para outro. Para que voc possa ver a estimativa de quantidade e tamanho das linhas afetadas, basta posicionar o cursor sobre a seta. Neste cenrio, sempre d uma ateno especial s setas mais grossas, pois uma linha muito grossa pode indicar uma alta operao de I/O. Para solucionar este tipo de problema voc deve tentar fazer com que as setas fiquem mais finas possvel e aqui novamente entra a clusula WHERE. Por outro lado, evite obter mais linhas que o necessrio.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Quinto Ponto: Bookmark Lookups

O operador Bookmark Lookup ocorre em conjunto com um nonclustered index seek quando a consulta deve obter colunas que no esto disponveis dentro do nonclustered index. Neste cenrio, procure por Bookmark Lookup que possua um alto percentual de consumo. Se o custo da operao de Bookmark Lookup for muito alto, verifique se um ndice cluster ou um ndice no cluster composto pelas devidas colunas (covering index) pode ser utilizado.

Sexto Ponto: Sorting

Um operador SORT ordena todas as linhas de entrada em uma ordem ascendente ou descendente. Isto depende da clusula ORDER BY de sua consulta. Operadores Sort normalmente acrescentam uma grande taxa de I/O s operaes, primariamente utilizando o TEMPDB para suas operaes. Se voc costuma ver o operador SORT com muita freqncia em suas consultas e este operador possui um alto consumo de operao, considere por remover a clusula ORDER BY. Por outro lado, se voc sabe que sempre ordenar sua consulta por uma coluna em especfico, considere index-la. Lembre-se que no comando CREATE INDEX voc pode fixar a direo de ordenao (ASC ou DESC) para um ndice em particular, e que um clustered index j possui ordenao nativa em nvel de tabela.
Nota:

O Profiler uma excelente ferramenta para ajudar na identificao de queries muito pesadas que possuem um alto tempo de execuo, ou que estejam sendo recompiladas a cada execuo. Veja o prximo Tpico sobre esse assunto. Para elucidar se a melhora obtida foi alcanada de forma substancial utilize a medio em milesegundos. Leia a seo de Dicas Gerais.

Nota2:

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Cenrio para estudo: O cenrio a seguir um bom alvo de estudo. Repare que a query em questo, apesar de ser bem simples, causa quase um "pnico" no SQL Server no momento de montagem do plano de execuo, demorando algo em torno de 20 segundos !! Cenrio Tabela: APL_VIDA_AE_HIST Linhas : 2.923.301 (quase 3 milhes de linhas !!) Primary Key: ID_VIDA_AE (PK_APL_VIDA_AE_HIST) ndice: ID_SUBESTIPULANTE (IF_APL_VIDA_AE_HIST_02) Tempo de execuo: 19800 milesegundos Filtro: ID_SUBESTIPULANTE e TP_SEGURADO

Note tambm o custo da execuo na tabela APL_VIDA_AE_HIST:

Alm de um CLUSTERED INDEX SCAN o plano de execuo apresentou a necessidade de converso do datatype da coluna ID_SUBESTIPULANTE.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Note que a PK composta por uma coluna que NO a que usamos no WHERE (id_subestipulante). A degradao ocorreu, mesmo no tendo evidncia razovel para tanto. Agora vamos a alguns fatos: - A tabela possui grande quantidade de linhas e o perfeito tratamento envolvendo ndices e converses extremamente fundamental. - A tabela possui uma Primary Key que no contm a coluna id_subestipulante e mesmo assim utilizou esse caminho. - A tabela possui um ndice pela coluna id_subestipulante e mesmo assim NO o utilizou. - A coluna id_subestipulante j numrica e mesmo assim foi convertida internamente pelo plano de execuo. Resolvendo a questo: 1) Use o mesmo datatype na varivel. Na tabela a coluna id_subestipulante do tipo INT e no BIGINT. Com isso eliminamos a converso e fica assim:

2) Podemos criar um ndice ou utilizar o Index Tunning Wizard para averiguar. O Index Tunning Wizard detectou o seguinte:

E recomendou:
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

A sugesto da criao do ndice foi salva e temos:


/* Created by: Index Tuning Wizard /* Date: 14/2/2007 /* Time: 09:57:38 /* Server Name: BORNATO /* Database Name: SISE_DES USE [SISE_DES] go SET SET SET SET SET SET SET go QUOTED_IDENTIFIER ON ARITHABORT ON CONCAT_NULL_YIELDS_NULL ON ANSI_NULLS ON ANSI_PADDING ON ANSI_WARNINGS ON NUMERIC_ROUNDABORT OFF */ */ */ */ */

DECLARE @bErrors as bit BEGIN TRANSACTION SET @bErrors = 0 CREATE NONCLUSTERED INDEX [APL_VIDA_AE_HIST7] ON [dbo].[APL_VIDA_AE_HIST] ([TP_SEGURADO] ASC, [ID_SUBESTIPULANTE] ASC ) IF( @@error <> 0 ) SET @bErrors = 1 IF( @bErrors = 0 ) COMMIT TRANSACTION ELSE ROLLBACK TRANSACTION

/* Statistics to support recommendations */ CREATE STATISTICS [hind_1370240432_1A_5A] ON [dbo].[APL_VIDA_AE_HIST] ([ID_SUBESTIPULANTE], [TP_SEGURADO])

Execute esse script, alterando o nome da estatstica sugerida para um nome mais familiar ou deixe essa parte para os DBAs analisarem. Agora podemos re-executar a query e tirar novas concluses.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Com esse tempo de resposta daramos por concludo esse passo. Tivemos um ganho de 20 segundos. Mas ainda resta a dvida: Porque o SQL no utilizou o ndice da coluna id_subestipulante, visto que essa coluna est na condio WHERE? Antes de entrar nessa questo, vamos utilizar o indicador HINT (INDEX=IF_APL_VIDA_AE_HIST_02). A execuo dura praticamente o mesmo tempo que obtivemos no passo anterior com a criao do ndice.

Ento surge outra dvida: Se o SQL capaz de detectar a melhor forma de obter um resultado atravs de seu imbatvel plano de execuo, porque nesse caso ele "falhou" e tivemos que dar uma ajudinha? Tudo agora se resume ao plano de execuo compilado. O importante saber distinguir varivel de parmetro. Varivel criada dinamicamente e o SQL vai descobrir o que fazer no momento da execuo.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Parmetros so armazenados no plano de execuo e o SQL j determinou o que e como deve ser feito. Note que, no caso do Procedimento Armazenado, no precisamos usar o HINT de INDEX no Procedimento e o ndice mais apropriado foi utilizado, opostamente foi o resultado da query "avulsa" que demorou 20 segundos.

Figura 1: O mesmo statement executado em um Procedimento Armazenado e avulso, degradao sem uso de Procedimento Armazenado.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 2: Tivemos que utilizar HINT de INDEX para ajudar o SQL a traar o melhor caminho.

Figura 3: Planos de execuo com uso de HINT em query avulsa (query 1) e de Procedimento Armazenado (query 3).

Apesar do plano de execuo ser diferente, o tempo de execuo em ambos os casos foi praticamente o mesmo. No foi preciso criar ndice para chegarmos a esse resultado. O ndice j existente na coluna id_subestipulante foi utilizado quando executamos a mesma query em Procedimento Armazenado. Porque o Index Tunning Wizard sugeriu a criao de um novo ndice ? A condio tp_segurado = 'P' na clusula WHERE confundiu a ferramenta que acabou por sugerir a criao de um ndice contendo esse campo tambm. Antes de criarmos um ndice devemos analisar se realmente necessrio. Para comprovar essa teoria, apenas retire a condio tp_segurado = 'P' e execute novamente o comando.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Notamos agora que o ndice da coluna id_subestipulante foi utilizado de forma correta, e assim, o tempo de execuo foi perfeito. Consecutivamente o Index Tunning Wizard no encontrar sugesto para esse caso.

Figura 4: Execuo do mesmo comando, agora sem a condio tp_segurado = 'P' e sem indicar o HINT

Importante: Quando fizermos diagnstico de funcionamento, no devemos recortar os blocos e executlos em separado, pois podemos ter um falso testemunho e nos induzir a erros de percia. Utilize sempre medies sobre o prprio Procedimento Armazenado, ou crie um para testes de medies. Tambm devemos executar uma limpeza do cache de dados e de Procedimentos Armazenados. Para isso coloque no escopo do Query Analyzer os seguintes comandos:
DBCC FREEPROCCACHE DBCC DROPCLEANBUFFERS

Questo: Se fizermos um GROUP BY no campo id_subestipulante o ndice ser utilizado? No. No ser utilizado o ndice apropriado mesmo com o agrupamento do campo id_subestipulante. O ndice da PK (cluster) continuar sendo o guia dessa query.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 5: Tentativa frustrada de usar o ndice correto apenas fazendo o agrupamento pela coluna id_subestipulante que possui o ndice correto.

Isso mostra que a interao do DBA e do analista fato importante na tomada de deciso da criao de ndices. A ferramenta Index Tunning Wizard serve como referncia apenas, todo o resultado sugerido pela ferramenta deve ser analisado antes da implementao. Se voltarmos o datatype do parmetro @idsubestipulante para o valor originalmente proposto (BIGINT), obteremos o seguinte:

Figura 6: Execuo de comando com varivel diferente do datatype. Plano de execuo diferente.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Note a evidncia de que o plano de execuo agora possui passos diferentes. Esses passos no agregaram tempo nossa execuo, porm precisa ser evitado o uso de datatypes diferentes, mesmo que compatveis. Assim a leitura do plano mais legvel e, o mais importante, em um ambiente de alta concorrncia essas precaues valem ouro. Os milsimos de segundos poupados somam at segundos em grande escala de execues.

Medio simples em milesegundos.


Aps os ajustes e uso do Plano de Execuo do Query Analyzer, ou quando houver a necessidade de elucidar se a melhora obtida foi alcanada de forma substancial - ou se foi "elas-por-elas" - utilize a medio em milesegundos.
set nocount on declare @vdate as datetime declare @cd_empresa int, @cd_sucursal int, @cd_rm int, @nro_apolice int, @NM_RM varchar(50) SET SET set set set @cd_empresa @cd_suc @cd_rm @nro_apol @NM_RM = = = = = 686 5310 720 2765 'VIDA EM'

set @vdate = getdate() /*Comente os campos do select e use o count(*) para medir os relacionamentos e no deixar que o delay de tela interfira na medio, pois nesse caso o ganho esperado est em milesegundos e o consumo de memria de vdeo, que o resultset trar, poder interferir na medio. Aps a medio mea tambm com as colunas do select.*/ select count(*) from apl_contrato as CONT inner join tbg_empresa as EMP on emp.cd_empresa = cont.cd_empresa inner join tbg_sucursal as SUC on suc.cd_empresa = cont.cd_empresa and suc.cd_sucursal = cont.cd_sucursal inner join tbg_ramo as RAM on ram.cd_rm = cont.cd_rm inner join apl_subestipulante as SUB on sub.id_contrato = cont.id_contrato inner join apl_subestipulante_plano as SUBP on subp.id_subestipulante = sub.id_subestipulante inner join apl_certificado as CER on cer.id_subestipulante = sub.id_subestipulante and cer.nro_certificado = 0 inner join apl_endosso as ENDO on endo.id_subestipulante = sub.id_subestipulante and endo.tp_endosso = '11' -- cobrana and endo.dt_cancelamento = '40001231' inner join cbr_cobranca as COB on cob.id_cobranca = endo.id_cobranca left join rgr_mod_geral as RGR on rgr.id_origem = cer.id_origem and rgr.cd_modulo = 'MDAE' and rgr.cd_regra = 318 where sub.idc_status = 'a' -- ativos and (@cd_empresa is null or cont.cd_empresa = (case when @cd_empresa is not null then @cd_empresa else cont.cd_empresa end)) and (@cd_suc is null or cont.cd_sucursal = (case when @cd_suc is not null then @cd_suc else cont.cd_sucursal end)) and (@cd_rm is null or cont.cd_rm = (case when @cd_rm is not null then @cd_rm else cont.cd_rm end)) and (@nro_apol is null or cont.nro_apolice = (case when @nro_apol is not null then @nro_apol else cont.nro_apolice end)) and (@NM_RM is null or ram.nm_rm like (case when @NM_RM is not null then @NM_RM + '%' else ram.nm_rm end)) select 'Tempo ' + cast( datediff(ms, @vdate, getdate()) as varchar) + ' milesegundos.'

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Profiler e Index Wizard


Agora entraremos na investigao tcnica das causas de baixa performance para orientar melhorias no cdigo de consultas e Procedimento Armazenado do banco de dados. As queixas quanto ao tempo de resposta, usualmente denigrem bons trabalhos de programao da aplicao, deixando todas as qualidades da mesma ofuscadas. muito importante para a soluo do problema de performance saber qual a origem do consumo excessivo de recursos do servidor, essa justamente nossa dificuldade. Iniciando O primeiro passo da investigao a ferramenta profiler, que instalada junto com o SQL Server. Precisamos configurar o profiler para mostrar os comandos que tm execuo mais demorada no servidor de banco de dados e, por isso mesmo, so candidatas a uma investigao mais profunda. Alm do texto do comando, sero coletados o tempo de execuo, nome da aplicao que fez a chamada e login utilizado, todos sero teis em nossa investigao.

USANDO O PROFILER A ferramenta Profiler pode ser acionada atravs do menu do prprio Enterprise Manager do SQL Server. Depois de aberto, no menu "FILE", escolheremos a opo "NEW TRACE". Logo em seguida, deve-se logar no SQL Server com uma conta que tenha poderes de sysadmin. Na aba "General" colocaremos o nome do trace. Na Figura 1 mostra que o profiler permite que o resultado seja salvo em uma tabela do prprio SQL. Esse recurso pode ser til para auditorias do servidor SQL, como investigar comandos mal intencionados. Para utilizao posterior, salvaremos o resultado do trace em um arquivo no disco (no exemplo, c:\temp\AnalisePerformance.trc). tambm utilizada pelos DBAs quando a equipe no possui usurio com permisso apropriada para executar o trace. O profiler deve ser executado em um horrio de grande uso, inclusive, incentivar os usurios a usar a parte da aplicao que consideram problemtica, pois assim os comandos respectivos sero capturados.

Figura 1 - Configurando para gravar o trace em disco

O que Monitorar
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Na aba "EVENTS" usaremos os eventos pr-selecionados, mas podem ser ressaltados os eventos de erro ("Errors and Warnings"), Locks e Security Audit. O profiler pode capturar um erro enviado para a aplicao, como uma chave primaria violada, e exibi-lo no resultado do profiler. til para verificar erros quando a aplicao tem uma rotina de tratamento que esconde ou os trata incorretamente.

Figura 2 - Usar apenas os eventos default (pr-selecionados)

Mover o campo "Duration", da aba Data Columns, para cima de modo que nosso resultado seja agrupado por durao. Adicione o campo "HostName" da lista esquerda para a lista de campos. A configurao final deve ser igual a da figura 3.

Figura 3 - Configurao dos campos do trace

Filtrar o Resultado
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Podemos ainda filtrar o trace. Podemos filtrar por uma aplicao especfica, um determinado usurio ou diversas outras opes. Em produo devemos filtrar e exibir comandos com durao em no mnimo 2 segundos (2000 milesegundos). Em desenvolvimento podemos especificar algo em torno de 1 segundo.

Figura 4a - Filtrando o trace por durao

Ou ainda poderemos filtrar somente um determinado objeto.

Figura 4b - Filtrando o trace por um objeto especfico

Rode o trace (boto "Run"), e o profiler comear a exibir a lista de comandos executados.
14/10/2008 - 22:36 Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc 0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 5 - Trace em atividade

Nesse caso tivemos um bom resultado. Vamos agora criar uma condio que requer ajustes para podermos testar outra ferramenta, o Index Wizard.

Aes Index Wizard


A ferramenta Index Wizard pode ser utilizada para checar automaticamente o resultado do trace. Para explorarmos de forma ordenada essa ferramenta, criaremos uma tabela teste na base northwind ou em outra base de testes:
USE Northwind GO SET NOCOUNT ON CREATE TABLE teste(c1 int IDENTITY(1,1),c2 char(500) DEFAULT '') GO WHILE @@IDENTITY < 10000 or @@IDENTITY IS NULL INSERT teste DEFAULT VALUES

Aps a criao, feche a janela do query analyzer e em outra janela digite a seguinte query.
SELECT c1 FROM teste WHERE c1=543

No menu "Query" use "Show estimated execution plan". A query executou um table scan (varredura completa da tabela), o que freqentemente est associado falta de ndices ou cdigo equivocado.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 6 - Plano de execuo (Table scan)

A partir do menu "Query", clique "Index Tuning Wizard". Mtodo de otimizao de Fast (Rpido) at Thorough (Completo). Existe a opo de manter os ndices existentes (caso contrrio o wizard pode recomendar a remoo de um ndice sem uso ou inadequado) e recomendar a criao de Vises indexadas se necessrio.

Figura 7 - Opes do wizard

Na prxima tela temos a opo de analisar um arquivo de trace, uma tabela de trace ou nossa query em questo. Usar "SQL Query Analyzer Selection", prosseguindo com o wizard. Selecione a tabela Teste que o alvo da nossa otimizao. Na seqncia do wizard podem ser vistas as recomendaes de nova indexao para a query analisada e, inclusive, uma projeo de melhora de performance, que nesse caso chegou a 98%.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 8 - Recomendaes de indexao do Index Wizard

Clicando em Analysis podemos analisar a prospeco sugerida.

Figura 9 Prospeco da sugesto do Index Wizard

Para criao manual, selecione "Save script file". Sempre grave antes e analise antes de sugerir qualquer modificao.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Figura 10 - Gravando recomendaes em arquivo

A seguinte sada ser gerada no arquivo:


/* Created by: Index Tuning Wizard /* Date: 13/2/2007 /* Time: 16:14:18 /* Server Name: BORNATO /* Database Name: Northwind USE [Northwind] go SET SET SET SET SET SET SET go QUOTED_IDENTIFIER ON ARITHABORT ON CONCAT_NULL_YIELDS_NULL ON ANSI_NULLS ON ANSI_PADDING ON ANSI_WARNINGS ON NUMERIC_ROUNDABORT OFF */ */ */ */ */

DECLARE @bErrors as bit BEGIN TRANSACTION SET @bErrors = 0 CREATE NONCLUSTERED INDEX [teste1] ON [dbo].[teste] ([c1] ASC ) IF( @@error <> 0 ) SET @bErrors = 1 IF( @bErrors = 0 ) COMMIT TRANSACTION ELSE ROLLBACK TRANSACTION

Compare os resultados do SELECT antes e depois da criao do ndice usando as estatsticas - SET STATISTICS IO ON. (diminuio de 770 leituras para apenas 2):
SET STATISTICS IO ON SELECT c1 FROM teste WHERE C1 =543 c1 ----------543 Table 'teste'. Scan count 1, logical reads 770, physical reads 0, read-ahead reads 0.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1
Lista 4 - Resultado da query sem ndice: 770 leituras x 8KB c1 ----------543 Table 'teste'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0. Lista 5 - Resultado da query aps criao do ndice: 2 leituras x 8KB

Veja o plano de execuo final.

Figura 11 - Plano de execuo aps criao do ndice

NOTA: O Profiler e o Index Wizard dispem de recursos que vo muito alm do exposto aqui e podem ser alvo de estudo e uso adicional.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Conceitos SQL-Server

rea DBA
Programao / Tunning - Reviso 1.1

Consideraes Finais
Antes de dar como concluda uma atividade, reveja e tente alterar a ordem das tabelas envolvidas, bem como procurar analisar se todas as tabelas so realmente necessrias, se as converses esto feitas corretas e se os ndices apropriados esto sendo utilizados de forma correta. Analise o plano de execuo em todos os casos. A cada linha que modificar no cdigo procure executar a query para analisar o impacto pelo o plano de execuo. Quanto mais registros estiverem disponveis para efetuar os testes, melhor. Muitas vezes as regras podem no parecer aplicveis determinada situao. Essa margem existe e aceitvel devido a uma srie de fatores que compe os diversos cenrios em que nos deparamos durante um tunning ou desenvolvimento. Portanto, como dica bsica, tente alternar entre as diversas tcnicas descritas desse documento para eleger a melhor soluo para cada caso. Nenhum cdigo to bom que no possa ser melhorado.

14/10/2008 - 22:36

Conceitos Prticos de Programao e Tunning no Microsoft SQL Server 2000.doc

0 / 49

Você também pode gostar