Archive

Posts Tagged ‘best pratices’

Desafio T-SQL

Ola pessoal, tudo bem?

Essa semana presenciei um caso aonde era necessário ajudar a desenvolver uma instrução T-SQL que fugia um pouco do nosso dia-a-dia, devido a isso resolvir postar no blog um desafio para compartilhar com todos a solução depois. Espero que muitas pessoas participem.

Vamos ao cenário.

Imagine que o Sistema X realiza o “track” de contratos de uma instituição financeira que são gerados pelo sistema Y, no entanto,o sistema Y gera mais de UMA LINHA para cada contrato toda vez que esse contrato é renegociado. Isso significa que, cada conjunto de contrato no sistema Y terá mais de uma linha baseando-se no número de contrato mais codigo de movimentação do mesmo (Contrato + Mov). Vejam um sample dos dados, conforme a seguir:

O sistema X precisa transformar o resulte set da imagem anterior em um único registro levando as seguintes regras em consideração:

  1. O status 0 significa – Precisa ser avaliado. O Status 1 significa: Registro Válido e o Status 2 significa que o registro pode ser descartado.
  2. Se o os valores em Dt1 e Dt2 for NULOS para para um conjunto de registro (Contrato + Processo) utilizo o registro com a MENOR DtReal.
    1. Obs: O print não atende essa condição, mas, consideraria asegunda linha da minha tabela:

       

       

  3. Se algum dos valores em Dt1 e Dt2 não for NULO para um conjunto de registro (Contrato + Processo) utilizo o registro com a MAIOR DtReal como base.
  4. Quando a regra de número 3 for atendida é necessário “montar” o registro com a seguinte “sub-regra”:
    1. Se o MAX VALUE da coluna Dt1 do conjunto de registro (Contrato + Processo) for maior ou igual a minha DtReal da linha atual, considero o MAX (no caso o valor 25/08/2013) para essa coluna. (Nesse caso minha coluna DtReal seria 22/08/2013 + Dt1 = 25/08/2013). No entanto, temos outra “regrinha” que no caso a regra “4.b”.
    2. Se o MAX VALUE da coluna Dt1 do conjunto de registro (Contrato + Processo) for maior ou igual ao MAX VALUE da DtReal do conjunto de registro (Contrato + Processo) o valor da coluna DtReal DEVE ser a menor data.O registro deve ser como a seguir:

       

  5. Se o MAX VALUE da coluna Dt1 do conjunto de registro (Contrato + Processo) NÃO for maior que a minha linha BASE (no caso a DtReal=22/08/2013, seguindo a regra de número 3) , conforme print:

    Nesse caso minha linha deve ser montada da seguinte maneira:

  6. Minha última regra consiste no seguinte: Se o MAX VALUE da coluna Dt1 do conjunto de registro (Contrato + Processo) NÃO for maior que a minha linha BASE (no caso a DtReal=22/08/2013, seguindo a regra de número 3) E o valor da Coluna Dt1 da linha BASE (no caso a linha que possi o valor DtReal = 22/08/2013) NÃO for NULA, minha linha consiste na DtReal + Dt1 daquela linha. Veja o cenário:

     

    Para a regra de número 6 o meu registro deve ser algo mais o menos assim:

     

     

Observações:

  • Os registros que devem aparecer na solução no final devem ter o valor da coluna Status modificado para 1
  • A solução pode ser escrita nas seguintes versões do SQL Server: 2008,200R2, 2012 e 2014.
  • A solução pode ser feita em mais de uma consulta para atender as regras.
  • Não é permitido a ulização de abordagens linha-a-linha (While e CUSRSOR)

Estou disponibilizando o script que monta os cenários com todos os registros. A ideeia inicial é desenvolver um pouco a lógica e fazer exercícios de T-SQL. No futuro podemos utilizar o mesmo cenário e avaliar o desempenho das sugestões que serão enviadas e discutir todas elas.

use tempdb

go

–Create sample datas

CREATE
TABLE #T
(Contrato VARCHAR(50), Mov INT, DtReal date, Dt1 date, Dt2 date,[Status] tinyint)

–DROP TABLE #T

INSERT
INTO #T(Contrato, Mov,DtReal,Dt1,Dt2, [Status])


VALUES


(’00XXXXX.25.0000′, 80193, ‘20130701’,
NULL        ,NULL,0)


,(’00XXXXX.25.0000′, 80193, ‘20130617’,
NULL        ,NULL,0)


,(’00XXXXX.25.0000′, 80193, ‘20130821’, ‘20130825’    ,NULL,0)


,(’00XXXXX.25.0000′, 80193, ‘20130822’,
NULL        ,NULL,0)

 

            ,(’00YYYYY.26.0000′, 80192, ‘20130701’, ‘20130820’    ,NULL,0)


,(’00YYYYY.26.0000′, 80192, ‘20130617’,
NULL        ,NULL,0)


,(’00YYYYY.26.0000′, 80192, ‘20130821’,
NULL        ,NULL,0)


,(’00YYYYY.26.0000′, 80192, ‘20130822’,
NULL        ,NULL,0)

 


,(’00ZZZZZ.27.0000′, 80194, ‘20130701’,
NULL        ,NULL,0)


,(’00ZZZZZ.27.0000′, 80194, ‘20130617’, ‘20130825’    ,NULL,0)


,(’00ZZZZZ.27.0000′, 80194, ‘20130821’,
NULL        ,NULL,0)


,(’00ZZZZZ.27.0000′, 80194, ‘20130822’, ‘20130821’    ,NULL,0)

 


,(’00WWWWW.28.0000′, 80195, ‘20130701’,
NULL        ,NULL,0)


,(’00WWWWW.28.0000′, 80195, ‘20130617’, ‘20130820’    ,NULL,0)


,(’00WWWWW.28.0000′, 80195, ‘20130821’,
NULL        ,NULL,0)


,(’00WWWWW.28.0000′, 80195, ‘20130822’, ‘20130821’    ,NULL,0)

 

            ,(’00KKKKK.29.0000′, 80196, ‘20130701’,
NULL        ,NULL,0)


,(’00KKKKK.29.0000′, 80196, ‘20130617’,
NULL        ,NULL,0)


,(’00KKKKK.29.0000′, 80196, ‘20130821’,
NULL        ,NULL,0)


,(’00KKKKK.29.0000′, 80196, ‘20130822’,
NULL        ,NULL,0)

 

            ,(’00AAAAA.30.0000′, 80196, ‘20130701’,
NULL        ,NULL,0)


,(’00AAAAA.30.0000′, 80196, ‘20130602’,
NULL        ,NULL,0)


,(’00AAAAA.30.0000′, 80196, ‘20130821’,
NULL        ,NULL,0)


,(’00AAAAA.30.0000′, 80196, ‘20130822’,
NULL        ,NULL,0)

 

            ,(’00BBBBB.19.0000′, 80196, ‘20130701’,
NULL        ,NULL,0)


,(’00BBBBB.19.0000′, 80196, ‘20130502’,
NULL        ,NULL,0)


,(’00BBBBB.19.0000′, 80196, ‘20130821’,
NULL        ,NULL,0)


,(’00BBBBB.19.0000′, 80196, ‘20130822’,
NULL        ,NULL,0)

 

Aguardo o script com a solução por e-mail. Fiquem a vontade para discutirmos. O Resultado da consulta deve ser o da imagem abaixo:

Thiago Carlos [TC] de Alencar

Especificação de Capacidade Máxima no SQL Server

Pessoal, boa tarde.

Hoje apenas apareci para dar uma dica rápida e acredito que seja de interesse em geral…rsrs. Quem nunca se pegou pensando: Qual a capacidade máxima de colunas em uma instrução SELECT ? Qual a quantidade de linhas por tabela? Ou até mesmo tabelas por database? “Passeando” pelo BING uma pesquisa me direcionou para um link no MSDN que gostaria de compartilhar com vocês. O link se refere a Capacidade máxima de especificação do SQL Server:

http://msdn.microsoft.com/en-us/library/ms143432.aspx

Muito Obrigado.

Abs

Atualizando a Edição do SQL Server 2008

Caros, bom dia.

Este post é dedicado ao meu amigo Lucas Souza, um DBA com quem venho aprendendo muito. Está sempre me acompanhando nos processos aqui na empresa e me instruindo.

Hoje vamos falar sobre um assunto bastante simples, porém, foi a primeira vez que tive que realizar o procedimento, atualizar a edição do SQL Server. Hoje temos aqui na empresa o ambiente de desenvolvimento, produção, testes e homologação. Junto com a equipe começamos uma iniciativa de padronizar a instalação do SQL Server, isso inclui Edição utilizada, service pack e cumulative updates. Após baixar o SP2 da versão do SQL Server 2008 R2, comecei a aplicar a instalação no ambiente de desenvolvimento, testes e homologação. Quando me deparei com um ambiente de homologação que está com a versão Standard do produto. E agora? Preciso reinstalar o SQL Serve novamente? Claro que não…

Vamos ao passo-a-passo

Inicialmente você deve copiar o instalador do SQL Server para a máquina qual deseja atualizar. De um duplo clique no setup.exe a seguinte tela será apresentada:

Clique em Yes e aparecerá o SQL Server Installation Center. No lado esquerdo clique em Maintenance.

Clique no Edition Upgrade, após isso, apenas devemos seguir os passos. Vamos fazer juntos?

O SQL Server irá fazer uma verificação, se todos os itens verificados passarem por essa verificação, prossiga. Caso algum item falhar, recomendo que seja ajustadoo item em questão e o processo seja refeito.

É altamente recomendado que todos os itens sejam aprovados no check que o SQL Server faz, só assim podemos garantir que não teremos problema futuramente.

Clique em OK.

Esse processo é bem parecido com o processo de instalação, após o OK confirmado na tela acima, aparecerá a opção da chave do produto, Clique em Next:

Marque o checkbox de “Aceito os termos” e clique em next:

Na próxima tela, podemos perceber que o instalador traz a versão atual do produto e para qual instancia será feito o “upgrade”.

Clique em next.O SQL Server fará uma verificação antes de lhe dar a opção de Update.

Clique em next. Você verá um sumario bem importante, que diz para qual versão está sendo modificado o SQL Server, qual ação está sendo tomada (No caso Edition Upgrade) e a lista de features que sofrerão com esta atualização:

Clique em Upgrade. Após isso é só aguardar o SQL Server terminar de atualizar todos os binários necessários para essa atualização. Quando isso acontecer, reinicie a máquina.

Obs: No post não foi focado cuidados que devem ser tomados no caso dessa atualização. É uma boa prática sempre realizar backup dos databases de sistema, quando for realizar alguma alteração que afeta as configurações da instancia do SQL Server

Espero ter ajudado

Abs

Realizando Backups T-SQL

Como foi visto anteriormente, podemos usar o SSMS para criar rotinas de backups de maneira intuitiva e visual, mas, existe ocasiões que precisamos apenas fazer um backup de um banco de dados. É mais conveniente usar a linguagem T-SQL do Microsoft SQL Server, além de ser simples é mais rápido. Ou até mesmo quando precisamos criar rotinas de backup mais flexíveis.

Se conecte ao SQL Server:

Abra uma nova janela no SSMS e digite a seguinte linha de comando:
Syntax:

–Comando de Backup Full de banco de Dados

BACKUP DATABASE database

TO backup_device [ ,n ]

[ WITH with_options [ ,o ] ] ;

Exemplo:

BACKUP DATABASE [TMKT]

TO DISK = N’D:TMKT.BAK’ WITH INIT,

STATS = 10

Acima podemos ver que criar um backup via T-SQL é muito simples. Caso fosse necessário executar o backup de forma regular através de um schedule, era só colocar o comando T-SQL em um job. Abaixo cito as opções mais utilizadas no arquivo de backup, para mais informações sempre usem a documentação do produto.
Parâmetros:
INIT – Especifica que todos os conjuntos de backup devem ser substituídos, mas preserva o cabeçalho da mídia. Se INIT é especificado, nenhum conjunto de dados de backup existentes nesse dispositivo é substituído.

STATS [= percentage] – Exibe uma mensagem cada vez que uma percentagem concluída, e é usado para medir o progresso. Se o percentual for omitido, o SQL Server exibe uma mensagem após cada 10 por cento é concluída.
Obs: Existem outros parâmetros além dos dois citados acima, consulte o BOL (Books On Line) do SQL Server.

MIRROR TO = Cria um “espelho” do backup para um outro dispositivo. Em caso que você queira ter o “backup do backup”. Uma restrição muito importante para esta clausula é que todos os dispositivos de backup devem ser do mesmo tipo, por exemplo: Um backup não pode ser mandado para uma fita se uma das cópias foi feita em disco.

COPY_ONLY – Especifica que o backup será apenas uma cópia. O copy_only é criado independente de seu regular scheduler. Sem afetar a sequência dos logs. Essa feature foi disponibilizada a partir do SQL Server 2005.

Obs: Se a opção differential e copy_only forem usadas juntas, a opção copy_only é ignorada e o backup diferencial é criado. Quando você usa a opção copy_only em um baclup de log, a sequência não é afetada e os logs não são truncados.

Realizando Backups SSMS

Agora que sabemos quais opções de backup o SQL Server oferece, vamos ver como realiza-los. O SQL Server oferece diversas formas para a criação de backup: Vamos  as mais utilizadas, através do SQL Server Management Studio (SSMS) ou usando comandos Transact-SQL. Em ambos os casos, é possível criar todos os tipos de backups abordados acima.
Criando um backup através do SQL Server Management Studio (Maintenance Plain)

Para acessar as janelas de opções do Maintenance Plain se conecte ao servido, conforme mostra figura abaixo:

Expanda os nós do SSMS até o Maintenance Plain

Clique com o botão direito em cima do nome Maintenance Plans e escolha a opção New Maintenance Plans.

Aparecerá a caixa de diálogo para que você especifique o nome do Plano de Manutenção.

Clique em Ok.

Aparecerá o painel de desenvolvimento do Plano de Manutenção.

Clique e arraste o componente Maintenance Cleannup Task para a parte amarela, conforme imagem:

Dê um duplo clique sobre o componente e a seguinte tela aparecerá:

No textbox Folder é o caminho de onde ficarão os arquivos de backups que serão deletados.
O checkBox permite a opção de excluir backups dentro de subpastas. E no File Age você pode escolher o tempo que os arquivos serão deletados, por defaulr são 4 semanas. Clique no botão com reticências ao lado do textbox folder e aparecerá uma nova janela, para escolher o caminhos de onde estarão os backups.

No nosso Server essa estrutura de pasta já estava criada, portanto, é opcional aonde serão colocados os arquivos de backup.

Obs: Nunca coloque arquivos de backup no C: do servidor, sempre deixe-os em discos separados em caso de falhas não haverá perda dos mesmos.

Clique Ok.

A nossa janela de Maintenance Cleannup Task deve ficar da seguinte maneira:
Clique em Ok.

Clique e arraste para o Painel o componente de backup

Dê um duplo clique no componente

Backup Type: Tipo do backup que será feito Full, Transactional ou Differential, como foi falado no inicio do documento.
DataBases: Quais databases serão backupeadas.
All Databases = Todas os banco de dados
System DataBases = Todos os Bancos de sistema
All User Databases = Todos os banco de dados de usuários, exceto tempdb, model, msdb e master. Conforme figura:

Escolha All User Databases e clique em ok.

Nossa tela de backup deverá ficar da seguinte maneira

Clique em Ok.

Clique na seta verde do componente Maintenance Cleannup Task e arraste para o Back Up Database Task, e os componentes ficarão da seguinte maneira:

Clique no calendário no canto superior direito do painel, pois, será hora de fazer o Schedule da rotina.

A seguinte janela aparecerá:

Occurs: Frequencia com que a atividade irá ser executada, no nosso caso será Daily
Daily frequency: Qual o horário que irá acontecer a rotina.

A nossa janela deve ficar da seguinte maneira:

Clique em Ok.

Clique em Salvar (ícone do disquete na parte superior da tela).

Feche o SQL Server.
Automaticamente será criado um Job no SQL Server Agent do servidor de banco de dados.

Espero ter ajudado….

Performance começa na modelagem II

Boa noite galera! Como falei no meu post anterior, “apareci” novamente aqui para falar sobre modelagem. Vou mostrar alguns descuidos que podem causar futuro problemas de performance. Ou até mesmo causado por falta de conhecimento. E é aqui que nós profissionais de SQL Server entramos, pra ajudar os amigos de profissão e tirar dúvidas sempre quando possível.

Agora apresentarei as definições das formas normais:

1º Forma normal – Requer que todos os valores de colunas em uma tabela, sejam atômicos (ex., um número é um átomo, enquanto uma lista ou um conjunto não o são). Por exemplo, a normalização elimina grupos repetidos pondo-os cada um em uma tabela separada, conectando-os com uma chave primária ou estrangeira.

2º Forma normal –  Requer que não haja dependência funcional não-trivial de um atributo que não seja a chave, em parte da chave candidata.

3º Forma normal – Requer não haver dependências funcionais não-triviais de atributos que não sejam chave, em qualquer coisa exceto um superconjunto de uma chave candidata.

Referência: http://pt.wikipedia.org/wiki/Normaliza%C3%A7%C3%A3o_de_dados

Agora imagine que o programador ou o analista de sistemas recebeu a seguinte especificação:

Criar uma sistema de call center que recebe um lote de informações de clientes que devem receber ligações para venda de cartões. Porém, as informações são recebidas em um arquivo de texto, sendo que o nome do cliente, CPF do cliente, telefone residencial do cliente e telefone celular do cliente fazem parte de um único registro. Como em terra de cego que tem um olho é rei. Nosso ilustre amigo criou uma única tabela para receber os dados e assim facilitando o seu trabalho. A tabela ficou da seguinte forma:

USE MCITP
GO
IF OBJECT_ID(‘dbo.TB_CLIENTE’) IS NOT NULL
BEGIN
DROP TABLE dbo.TB_CLIENTE
END
GO
CREATE TABLE dbo.TB_CLIENTE
(
COD_CLI INT IDENTITY NOT NULL PRIMARY KEY,
CPF_CLI CHAR(11) NOT NULL ,
DD_TEL_RES CHAR(2) NOT NULL,
TEL_RES_CLI CHAR(8) NOT NULL,
DD_CEL_CLI CHAR(2) NOT NULL,
TEL_CEL_CLI CHAR(8) NOT NULL
)

Até aqui tudo parece perfeito, porém, a equipe gerencial deseja que uma tela de consulta seja criada e que seja possível realizar consulta por cpf, telefone residencial e telefone celular. Na tela todas os valores serão opcionais exceto cpf, teoricamente, deveria existir um índice para cada coluna, isso iria garantir que o SQL Server usasse o índice requisitado para a coluna escolhida como parâmetro.

O objetivo deste post não é falar sobre indexação ou estratégia de indexação. Esse assunto será abordado em um outro post com maiores detalhes e maiores abordagens. O que está sendo apresentando aqui acontece por ai no mercado, pois, esse é uma situação a qual eu já presenciei.

Voltando ao nosso assunto como todo mundo sabe que índice é “bom” para consultas, nosso amigo criou um índice para a coluna da cpf, telefone residencial e telefone celular.

USE MCITP
GO
CREATE NONCLUSTERED INDEX IX_CPF_CLI ON dbo.TB_CLIENTE (CPF_CLI)
GO
CREATE NONCLUSTERED INDEX IX_TEL_CLI ON dbo.TB_CLIENTE (DD_TEL_RES,TEL_RES_CLI)
GO
CREATE NONCLUSTERED INDEX IX_CEL_CLI ON dbo.TB_CLIENTE (DD_CEL_CLI,TEL_CEL_CLI)

Vamos aos fatos, um índice é uma faca de dois gumes. Em um ambiente OLTP temos muita leitura e criar índices ajuda a devolver os dados de forma mais eficaz e faz com que o SQL Server crie planos de execução mais eficientes. Por outro lado, quando você cria muito índice é possível que tenha baixa performance em instruções INSERT, UPDATE e DELETE. É correto afirmar que: O SQL Server organiza os índices em uma estrutura B-Tree (Esse assunto não será abordado neste post). E quando um índice clustered é atualizado ele deve manter os índices non-clustereds atualizados também. Já conseguiram sacar onde está o nosso possível overhead nas instruções que modificam os dados? Não! Então vamos lá!

Podemos ver que na consulta abaixo é possível verificar quais os índices que foram criados. Temos quatro índices. Um índice clustered para a coluna COD_CLI que é a nossa primary key  e os demais índices NONCLUSTEREDs que críamos anteriormente.

select i.name,i.type_desc from sys.indexes i
where i.object_id = OBJECT_ID(‘dbo.TB_CLIENTE’)

Como não realizamos nenhuma instrução sobre a nossa tabela TB_CLIENTE, podemos perceber que o nível folha e o nível intermediário da B-Tree não sofreu nenhuma modificação:

SELECT i.name,a.leaf_insert_count,a.nonleaf_insert_count
,a.leaf_delete_count,a.nonleaf_delete_count
,a.leaf_update_count,a.nonleaf_update_count
,a.leaf_allocation_count,a.page_lock_count
FROM sys.dm_db_index_operational_stats(DB_ID(‘mcitp’),OBJECT_ID(‘dbo.TB_CLIENTE’),NULL,NULL) as a
join sys.indexes i
on i.index_id = a.index_id
and i.object_id = a.object_id

Agora iremos realizar alguns inserts em nossa tabela e veremos o que acontece.

INSERT INTO dbo.TB_CLIENTE(CPF_CLI,DD_TEL_RES,TEL_RES_CLI,DD_CEL_CLI,TEL_CEL_CLI)
VALUES(‘7893652′,’11’,’24985236′,’11’,’78964521′)
,(‘7896325236′,’11’,’78965230′,’11’,’69365212′)
,(‘33209376325′,’11’,’78785225′,’11’,’80756312′)
,(‘33369863201′,’11’,’96785421′,’11’,’56365425′)

Executaremos novamente a query que traz as modificações feitas no nível folha e no nível intermediário para ver como a nossa estrutura está após os inserts:

Thiago! Continuo sem entender! Então vamos lá? O que aconteceu!? Como temos quatro índices na nossa tabela e realizamos quatro inserções, que dizer que: O SQL Server também atualizou todos os nossos índices nonclustereds no nível folha da nossa estrutura B-Tree como eu havia explicado anteriormente. Podemos ver que, muito índice em uma tabela que recebe alto nível de inserções pode prejudicar a performance. Imagine que eu precisasse importar 2000 linhas. O SQL Server escreveria 2000 linhas para o índice clustered e 2000 para cada índice nonclustered.

Mais e a atualização de registros, como ficaria ? Vejamos irei atualizar a coluna CPF_CLI para o cliente com o código 1.

UPDATE dbo.TB_CLIENTE SET CPF_CLI = ‘123654789’ WHERE COD_CLI = 1

Pronto! Agora com a atualização na coluna CPF_CLI podemos ver um aumento de valor na coluna leaf_insert_count para 5 no indice da coluna CPF. O registro também foi modificado no índice clustered, isso pode ser visto na coluna leaf_update_count que tem o valor de 1.  Mas porque no índice clustered? O índice clustered são os dados propriamente ditos, quando fizemos o update na coluna de cpf o SQL Server

Espero ter ajudado. Até o próximo post.

Performance começa na modelagem

Desempenho começa na Modelagem.

Bom dia, Querido blog, tempo que não escrevo em você….rs. Hoje estou aqui apenas para falar  aos leitores sobre algumas pequenas dicas de performance  que as vezes passam despercebidos aos nossos olhos.

Vamos à análise.
Uma página de dados no SQL Server ocupa 8192 bytes, sendo 8060 bytes para os dados e o restante para o header da página. É correto afirmar que: criar um índice em uma coluna do tipo de dados inteiro que possui 2015 linhas vai ter uma página de dados completamente preenchida:

Calculo: Tipo de dados * Qtde de Linhas
Calculo: Int 4 Bytes * 2015 Linhas = 8060 bytes.

Thiago não estou entendendo aonde você que chegar!? Simples, meu caro blog! Será que preciso de uma coluna do tipo de dados int para a minha tabela. Desenvolvedores, analistas, programadores e estagiários é aqui que a gente entra.

Quando modelar alguma necessidade de negócio, sempre temos que nos atentar a que tipo de dados vamos usar e se é realmente necessário este  tipo de dados para determinada coluna. Já vi em muitos casos tabelas de domínio que apenas guarda poucos valores com o tipo de dados inteiro. Vamos a um exemplo:

YODA deve desenvolver um sistema de venda de produtos e foi especificado que os produtos a serem vendidos, seriam divididos em categorias. YODA criou o seguinte script para a tabela de categoria:

USE tempdb
go
IF OBJECT_ID(‘dbo.CategoriaProduto’) IS NOT NULL
BEGIN
DROP TABLE dbo.CategoriaProduto
END
CREATE TABLE dbo.CategoriaProduto (COD INT IDENTITY, DESCRICAO VARCHAR(50))

GO

Agora vem a pergunta! Até quantos registros posso armazenar em um tipo de dados inteiro? Segundo a definição do meu melhor amigo (Books On line), podemos armazenar -2^31 (-2,147,483,648) to 2^31-1 (2,147,483,647). Será que preciso armazenar todas estas categorias? Se tivermos apenas 50 ou ate 250 categorias, poderíamos usar o tipo de dados tinyint. Com isso apenas usaríamos um byte de armazenamento. Mas preciso mesmo me preocupar com esses detalhes? Será que essa diferença em bytes pode afetar minha performance ? A resposta é SIM!. O usuário final ou até mesmo o desenvolvedor não pode sentir essa perda, porém, isso para o SQL Server é extremamente importante. Uma das questões é: Tomando esse devido cuidado com tipo de dados você pode economizar espaço em disco e cache. Pode acreditar o buffer pool agradece.

Como o SQL Server ler os dados?

Todos nós sabemos que a leitura em memória é mais rápida do que a leitura em disco. O SQL Server também sabe! Quando uma query é enviada ao SQL Server ele verifica se os dados estão em memória (Buffer Pool), antes de verificar se os dados do disco. Como os dados estão em memória o SQL Server apenas realiza leitura lógica (Não Física). Thiago! E o que tudo isso tem a ver com o que foi escrito anteriormente? SIMPLES. Quanto menor for o tipo de dados usado em nossas colunas, menor a quantidade de espaço iremos armazenar e mais informações teremos dentro do buffer pool, sendo assim, diminuindo o acesso ao disco e aumentando a quantidade de informações em memória.

Pessoal modelar é uma tarefa muito importante, então, por favor. Prestem atenção. Estarei criado mais posts referente a estes assuntos futuramente.

Dica rápida – Removendo NOT IN

Ola Galera, blz? Tô passando pra realizar um post na “velocidade da luz” devido ao curto espaço de tempo pra postar. Porém, essa duvida é meio que corriqueira no ambiente de desenvolvimento que passei. Quando temos um NOT IN, como podemos reescrever uma query? As vezes se soubermos como reescrever uma query de uma outra maneira e ela traz o mesmo resultado podemos obter ganho de performance. Mas, isso deve sempre ser testado para verificar se o ganho é verdadeiro(Esse assunto fica pra um outro post).

O Gustavo Maia escreveu um ótimo artigo sobre o assunto: http://gustavomaiaaguiar.wordpress.com/2009/01/18/piores-praticas-utilizacao-do-operador-not-in/

Evite usar o operador NOT IN para verificar inexistência de dados em tabelas. Se o uso deste operador for mesmo necessário, ele pode ser modificado por um left join, conforme Exemplo:

USE tempdb
go

IF EXISTS(SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(‘[dbo].[TB_CLIENTE]’) and type=’U’)

DROP TABLE [dbo].[TB_CLIENTE]

go

CREATE TABLE [dbo].[TB_CLIENTE] (COD int identity, NOME varchar(max))

go

INSERT INTO [dbo].[TB_CLIENTE](NOME)VALUES(‘Minha CONSULTORIA’)

INSERT INTO [dbo].[TB_CLIENTE](NOME)VALUES(‘Minha’)

INSERT INTO [dbo].[TB_CLIENTE](NOME)VALUES(‘Consultoria’)

GO

IF EXISTS(SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(‘[dbo].[TB_PEDIDO]’) and type=’U’)

DROP TABLE [dbo].[TB_PEDIDO]

go

CREATE TABLE [dbo].[TB_PEDIDO] (COD int identity, PRODUTO varchar(50), COD_CLI INT)

go

INSERT INTO [dbo].[TB_PEDIDO] (PRODUTO,COD_CLI)VALUES(‘NOTE BOOK’,1)

INSERT INTO [dbo].[TB_PEDIDO] (PRODUTO,COD_CLI)VALUES(‘CADERNO ESCOLAR’,1)

INSERT INTO [dbo].[TB_PEDIDO] (PRODUTO,COD_CLI)VALUES(‘REVISTA’,1)

INSERT INTO [dbo].[TB_PEDIDO] (PRODUTO,COD_CLI)VALUES(‘BICLICLETA’,2)

INSERT INTO [dbo].[TB_PEDIDO] (PRODUTO,COD_CLI)VALUES(‘TELEFONE CELULAR’,2)

INSERT INTO [dbo].[TB_PEDIDO] (PRODUTO,COD_CLI)VALUES(‘BOLA DE FUTEBOL’,2)

O script acima cria uma tabela de cliente e de pedidos. Imagine que você precisa retornar uma query que traz os clientes que NÃO tem pedidos. O pensamento inicial seria usar o NOT IN:

SELECT c.cod,c.nome FROM dbo.TB_CLIENTE c WHERE c.cod NOT IN (SELECT p.cod_cli FROM dbo.tb_pedido p)

O resultado seria:

A query poderia ser facilmente modificada para usar um left join obtendo o mesmo resultado.

 SELECT c.cod,c.nome, p.COD,p.COD_CLI FROM dbo.TB_CLIENTE c 
LEFT JOIN dbo.tb_pedido p 
on c.cod = p.cod_cli
where p.COD_CLI is null

Na velocidade da luz….rs.

Espero ter ajudado

Trouble shooting da TempDB SQL Server

Esse procedimento é dedicado ao meu amigo Jeferson Kiocia  que me  ensinou muitas coisas, sobre windows, Contadores de Performance, Infra,Storage e etc.. Na verdade ele me disse: “Faz um procedimento sobre algo quando “Ferrar” o disco da TempDB! Quando der uma M…. Você tem que ter a solução rápido”. E aqui estamos. Fica a dica: Sempre documente os procedimentos, mesmo, que ainda não tenha acontecido. Porque quando acontecer, você será cobrado e a dor de cabeça será tremenda e ainda você pode ouvir “Se você sabia que isso poderia acontecer, porque não fez um procedimento?”.

Quando usar este procedimento?

O procedimento deve ser usando quando o array que hospeda a tempdb falhar(Nunca deveria acontecer, leia no final do post). Quando isso acontece o SQL Server retorna um erro,pois, o caminho onde a tempdb estava não foi encontrado.

Cenário: Imagine um cenário que temos a tempdb em um disco de nome S, conforme print:

E esse disco falhou ou a letra não é mais a mesma(se você trocou a letra depois da falha). Quando o SQL Server iniciar na próxima vez ele retornará as seguintes mensagens no Event Viewer:

Erro:1

Erro:2


Erro:3

Quando aparecer qualquer dessas mensagens, que dizer que a tempdb não foi encontrada. A solução para esse tipo de problema é: Se conectar ao SQL Server via prompt de comando e alterar o arquivo da tempdb de unidade. Vá até a a pasta aonde encontra-se os binários do SQL Server.

Você deve acessar esse caminho via promt de comand, conforme print:

Digite a linha de comando abaixo para inicar o SQL Server pelo prompt.

Sqlservr.exe -f -m -sNomeDaInstancia

O print mostra a linha digitada:

Obs: O SQL Server Agent deve estar desabilitado para a execução desta linha de comando. Se o SQL Server estiver ativo, você não conseguirá usar o SQL em single user mode. Os parâmetros são explicados abaixo:
f ? Executa o sql server com as configurações minimas.
m ? Entra no sql server em single user mode.
s ? Nome da instancia do sql server. Esse nome pode ser obtido no SQL Server Configuration Manager.

Nome da Instancia.

Com o SQL Server iniciado no prompt que foi aberto:

Quando o SQL Server é inicado desta maneira, a tempdb por default vai para o diretorio de bases de dados padrão do SQL Server de instalação(aonde encontra-se a master, model e msdb). Abra um novo prompt do MS-DOS e use um utilitário de linha de comando para mudar a tempdb de diretório. Use a linha de comando abaixo:

osql.exe -E -sNomeDaInstancia

Conforme o print abaixo:

Obs: O parâmetro -E é a conexão trusted (integrada com o windows), o usuário que está executando este procedimento deve ter permissões de SA no SQL Server. Neste exemplo usamos o login TMKTSQLSVC que é uma conta do windows com permissões de SA.

Após conectado ao SQL Server, execute os comandos abaixo para modificar a tempdb para a nova unidade.

USE MASTER
GO
ALTER DATABASE tempdb MODIFY FILE
(NAME= tempdev, FILENAME= ‘F:/MSSQL2005/MSSQL/SYS_DBS/DATA/tempdb.mdf’)
GO
ALTER DATABASE tempdb MODIFY FILE
(NAME= templog, FILENAME= ‘F:/MSSQL2005/MSSQL/SYS_DBS/LOG/templog.ldf’)

O SQL Server retorna a mensagem que os arquivos da tempdb serão movidos após a próxima reinicialização do serviço do SQL Server.

Digite exit na janela aonde você digitou os comandos e aperte a tecla enter.
Na outra janela de prompt que está em aberta pressione CTRL C aparecerá uma mensagem solicitando confirmação se você deseja fazer o shutdown do SQL Server.

Pressione a tecla Y.

Inicie o SQL Server normalmente.

Após o procedimento o SQL Server deve subir normalmente.

Obs: Leitura no final do post: A tempdb sempre deve estar em um disco que oferece redundância, de preferência um disco com alta velocidade para escrita e leitura(RAID 10). Esse procedimento foi criado em um ambiente onde a tempdb estava em um RAIDO.

Espero ter ajudado.
Abssssss

Integrando os contadores do System Monitor ao SQL Server Profiler

Esse artigo é dedicado ao meu amigo Marcelo Fernandes da Silva (Misifio/D2). Graças a ele, estou no “mundo SQL Server”. Sempre está me incentivando e me dando uns helps.Quem o conhece sabe o quanto ele conhece(É muitooo viuuuu!) de SQL Server. Vamos ao trabalho.

Esse procedimento pode ser implementado em um ambiente que existe diversos sites, e você deseja realizar um procedimento pró-ativo de melhoria no ambiente começando pelo código T-SQL que é executado no mesmo.

Capturando Log Counters.

O primeiro passo é capturar as informações numericas relacionadas a gargalo de disco, processamento, memória e etc. Abra o System Monitor conforme figura abaixo:

Clique com o botão direito em Counters Log e escolha a opção New Log Settings..

Aparecerá uma caixa solicitando o nome do Counter Log a ser criado. Preencha e clique em OK.

Aparecerá a já nela de configurações dos contadores a ser escolhido.

Current log file name:  Caminho e Nome do arquivo do contador
Add Objects:  Lista de objetos do System Monitor
Add Counters:  Lista de Contadores do System Monitor
Interval: Intervalo de tempo em que os dados serão coletados
Run As: Credencial que irá executar o counter log e gravar os arquivos na pasta que será selecionada.

Clique em add counters para adicionarmos os contadores. No nosso exemplo será usado apenas alguns contadores do objeto processador. Clique em Add.

Na guia Log Files, você configura o tamanho que terá o arquivo do contadores e qual o caminho aonde o mesmo será gravado.

Clique em configure.

Será aberta a janela aonde o arquivo deverá ser salvo. Por default o arquivo é sempre salvo no diretório C:. Aqui nós criaremos uma pasta no diretório F: e apontaremos o caminho do arquivo para esta pasta(CountersSQL).

Clique em OK.

Na guia Schedule, podemos agendar o horário que o contador inicie, intervalo e etc. Não usaremos isso, pois, iniciaremos o mesmo manualmente.

Clique em OK

Voltando para a guia General. Preencha o textbox com a credencial que irá executar o contador e clique em Set Password. Abrirá uma janela parecida com a do print abaixo:

Obs: Neste exemplo estou usando a conta do serviço do SQL Server, pois, a mesma possui direitos de Admins do dominio. Sempre use uma conta que tem permissão de gravação na pasta no qual será gravado o log. Clique em OK. Depois clique em OK na guia General.

Na opção de counters Log irá aparecer o seu contador e qual caminho você salvou.


Clique com o botão direito e inicie o contador, o mesmo mudará de cor, conforme print:

Iremos para a segunda parte do procedimento

Unificando as ferramentas

Para que esta tarefa seja concluída você deve ter um arquivo do profiler que estava executando na mesma hora em que o Counter Log foi iniciado. Um dos pré-requisitos para que os dados sejam “mesclados” é que o profiler deve ter sido criado com a coluna Start Time selecionada.

Vamos partir do pressuposto que o arquivo do profiler já havia sido coletado e o counter log também. E que os mesmos foram executados durante o mesmo periodo.

Abra o profiler e vá em Open/File/Trace File

Navegue até a pasta aonde está salvo o arquivo .trc do profiler do SQL Server.

Clique em Abrir.
Novamente no Menu File escolha a seguinte opção:

Ao clicar nesta opção, você deverá passar o caminho aonde esta salvo o counter log que foi criado.

Clique em abrir.

A janela com os contadores que você escolheu anteriormente irá aparecer todos desmarcados. Marque os check box apenas do tempo total de processamento.

Obs: Você pode escolher mais que um contador, neste exemplo apenas usaremos o tempo de processamento. Apenas um contador facilita a visualização e se for um problema de processamento em um devido horário, não tem porque adicionar contadores de disco.

Após você escolher o contador o resultado será apresentado, conforme abaixo:

Você pode analisar em qual horário foi o pico de processamento e o que estava rodando no exato momento no profiler.

Espero que seja uma dica útil para alguém que esta começando….