SELECT CAST (power(CrazyIdeas, Curiosity) * (RealLifeExperience + MyMistakes)) / FreeTime) AS VARCHAR(MAX)) FROM MyBrain WITH (NOLOCK, INDEX('idx_Neuron')) WHERE ThingsIThinkIKnow in ('SQL Server', 'DB2', '.NET', 'Cloud')
sexta-feira, 30 de novembro de 2012
[SQLServerDF] Material do encontro XV - ColumnStore Index
terça-feira, 29 de maio de 2012
Filtered index, query hints e QO error 8622
sexta-feira, 2 de março de 2012
Otimizando o Data Cache
No dia 01/02/2012 eu publiquei uma pesquisa no meu blog para analisarmos como está o desperdício no data cache do seu SQL Server (http://luticm.blogspot.com/2012/01/pesquisa-desperdicio-no-data-cache.html).
Como vocês podem ver pelas repostas, é usual termos um desperdício de 8% a 15%, o que isso significa? Se você tem um data cache com 30 GB de tamanho, então algo entre 2,4GB e 4,5GB está sendo desperdiçado.
É claro que não tenho ilusão de que 100% do data cache estará ocupado, pelo contrário, temos fragmentação normal dos índices, níveis não folha e outras páginas de controle usualmente possuem espaço livre, então parte desse espaço em memória vai ser desperdiçado sim! Mas você como DBA deve cuidar para que o desperdício seja o menor possível. Como?
- Modelando corretamente seu banco de dados
- Usando outros recursos, como compressão de dados (cuidado sempre com os trade-offs).
- Garantindo a manutenção dos seus índices
- Tomando muito cuidado com thresholds globais Fillfactor? PADIndex? Fragmentação para reorganize e Rebuild? Na boa, quem já fez treinamento comigo sabe que sou bem ácido em relação a essas recomendações universalmente aceitas, usualmente elas podem te prejudicar muito.
Todos vocês podem ver o que os outros publicaram e tirar suas próprias conclusões, então dentro do que foi mostrado eu gostaria de propor uma nova verificação para todos os ambientes: tentar minimizar o desperdício do data cache!
Qual o threshold? (Opa, acabei de falar mal de thresholds globais! Shame on me :-))
Se o seu negócio permitir (normalmente sim), vamos com uma meta ambiciosa: manter o desperdício do data cache sempre abaixo de 10%.
E claro que nem sempre a coisa é simples e muitos detalhes podem tornar a vida do DBA mais complexa (e divertida, porque não?). Imagine o seguinte... Seu índice apresenta fragmentação interna de 3% mas o desperdício dela no data cache para este objeto é de 50%!
Sim, isso pode acontecer com você, é o que eu chamo de fragmentação de um ramo da árvore (B-tree+), principalmente quando suas tabelas começam a crescer demais e uma fragmentação em um ramo mais utilizado pode passar despercebida, quando analisado todo o índice.
Esse seria um post longo, mas acabei escolhendo por publicar o artigo no SimpleTalk (http://www.simple-talk.com/sql/database-administration/no-significant-fragmentation-look-closer%E2%80%A6/) para ver se tinha aceitação também lá fora.
Então você somente pode considerar que leu esse post depois de ler o artigo inteiro e deixar lá seu comentário e avaliação, seja boa ou ruim.
[]s
Luciano Caixeta Moreira - {Luti}
luciano.moreira@srnimbus.com.br
www.twitter.com/luticm
www.srnimbus.com.br
quinta-feira, 2 de junho de 2011
Primeiro treinamento online da Sr. Nimbus
************************************************************************************
!!UPDATE!!
Recebemos questionamentos sobre o formato do curso e algumas pessoas querem testar o Live Meeting, então hoje (08/06/2011), entre 21:00 e 21:30 eu estarei online no LM para tirar dúvidas com relação ao formato do curso, ementa, material, certificados, além claro, de já testar a conectividade do LM.
Link para sessão aberta: https://www.livemeeting.com/cc/mvp/join?id=9WM6CF&role=attend&pw=AlunoNimbus20110608
Perto do horário eu publicarei aqui e no twitter o endereço para vocês acessarem a sessão do Live Meeting.
IMPORTANTE: hoje de noite eu estarei com uma conexão de modem 3G que NÃO é a conexão do treinamento, mas atende o propósito pontual. Para o treinamento temos dedicado um link de 10MB da GVT, e por todos os testes que conduzimos podemos dizer que a conectividade ficou muito boa.
************************************************************************************
Colocamos no nosso site a inscrição para o primeiro treinamento online oferecido pela Sr. Nimbus. O treinamento será o novo SQL10 - Indexação no SQL Server 2008 e eu serei o instrutor dessa turma.
Nesse treinamento vamos focar em um dos assuntos mais fascinantes e importantes do SQL Server: índices! Ficaremos 16 horas discutindo sua estrutura, tipos, melhores práticas de utilização e otimização.
A ideia é nos aproximarmos ao máximo uma aula presencial, com um moderador repassando as perguntas para o instrutor, que responderá perguntas ao vivo, apresentaremos PPTs, demos e, em paralelo, o aluno terá acesso a todos os scripts que poderá ir executando confortávelmente em sua casa. Antes de cada aula também ficaremos por 30 minutos na sala de aula, tirando dúvidas dos alunos por chat ou respondendo em voz alta para todos.
Temos muita expectativa no excelente aproveitamento dos alunos e na satisfação de todos, pois é um formato mais democrático, que possibilita a participação de todos, independente de onde você esteja.
Gostou?! Veja todos os detalhes aqui: http://intranet.srnimbus.com.br/treinamento/paginas/inscricoes/SQL10-201101.aspx
Estou contando os dias para o treinamento.
[]s
Luciano Caixeta Moreira - {Luti}
luciano.moreira@srnimbus.com.br
www.twitter.com/luticm
www.srnimbus.com.br
terça-feira, 10 de maio de 2011
Treinamentos Sr. Nimbus e curso online
Recentemente temos recebido vários questionamentos sobre calendário e pedidos para que nossos treinamentos sejam executados em outros estados. Vamos a um rápido posicionamento:
- Não fechamos turma para os treinamentos de querying e programming por conta dos horários. Tínhamos demanda, mas as datas/horas não coincidiam para os alunos.
- Por conta dos nossos recursos, mais especificamente eu (sim, sou o culpado), tivemos que alterar o calendário por conta de alguns projetos em que estamos trabalhando. O que nos forçou a postergar algumas turmas para não fazer uma entrega corrida.
- Estamos trabalhando em um novo calendário para os próximos meses, em breve publicarei no site da empresa e farei o anúncio aqui também.
- O treinamento de database mirroring com o Gustavo Aguiar vai ser ministrado provavelmente em Junho. Estamos negociando uma parceria e trabalhando forte no conteúdo e, devo confessar, está espetacular.
Para nos ajudar, montei uma pequena enquete e gostaria MMMUUIITTTOOO que você nos ajudasse. Na enquete estão os detalhes para o primeiro treinamento.
Responda a pesquisa!
[]s
Luciano Caixeta Moreira - {Luti}
luciano.moreira@srnimbus.com.br
www.twitter.com/luticm
http://www.srnimbus.com.br/
quarta-feira, 15 de setembro de 2010
Non-SARG que nada! Enganei o SQL Server...
Prefere ler em PDF?
Ontem eu citei em uma palestra do Teched 2010 que um index seek exibido no plano de execução pode esconder na verdade um range scan ou até um full scan, então vou pegar um gancho de uma pergunta que apareceu recentemente em um treinamento que estava ministrando.
-- Consulta 01
SELECT orderdate, OrderID FROM Orders WHERE MONTH(OrderDate) = 07 and YEAR(OrderDate) = 1996
-- Consulta 02
SELECT OrderDate, OrderID FROM Orders WHERE OrderDate between '19960701' and '19960731 23:59:59.997'
Nesse momento um DBA fez uma observação muito curiosa: “eu posso enganar o SQL Server!” E para isso basta executar a consulta 03.
-- Consulta 03
SELECT OrderDate, OrderId FROM Orders WHERE MONTH(OrderDate) = 07 and YEAR(OrderDate) = 1996 and OrderDate > 0
(Figura 01)
Se olharmos com calma, o seek predicate é somente o “orderdate > 1990-01-01”, isto é, um belo scan no nosso índice não-cluster e enquanto o SQL Server está fazendo esse “seek”, ele vai tentando aplicar o predicado com MONTH e YEAR, que é o nosso non-sarg.
terça-feira, 23 de fevereiro de 2010
Artigo: Como o Query Optimizer utiliza (ou não) constraints unique e filtered indexes
Aproveitando o gancho do último post, escrevi hoje um artigo com duas intenções:
- Mostrar como o query optimizer do SQL Server se beneficia de constraints unique
- Mostrar uma característica do optimizer com filtered indexes que me parece um bug
Como o Query Optimizer utiliza (ou não) constraints unique e filtered indexes
Espero que vocês gostem e deixem aqui seus comentários...
[]s
Luciano Caixeta Moreira - {Luti}
Chief Innovation Officer
Sr. Nimbus Serviços em Tecnologia Ltda
luciano.moreira@srnimbus.com.br
www.twitter.com/luticm
sexta-feira, 19 de fevereiro de 2010
Colunas UNIQUE e NULLs
Se quiser baixar o PDF e o script que utilizei, clique aqui.
Durante o último treinamento do SQL Server 2008 Internals, tive mais uma vez o prazer de usufruir de uma das grandes vantagens de ser instrutor, que é aprender com os alunos, então compartilho com vocês.
Estávamos discutindo sobre a utilização do NULL e eu joguei na sala a pergunta: Como fazemos para manter a unicidade de uma coluna e ainda permitirmos diversos valores nulos?
(Pausa para respirar e pensar um pouquinho)
No SQL Server a unicidade dos valores em uma coluna é garantida através de índices marcados como UNIQUE (cluster ou não) e uma vez inserido um NULL, nenhum outro NULL pode ser adicionado a tabela, pois é um valor duplicado.
É interessante ver esse comportamento de igualdade de nulos em uma constraint, pois se testarmos a igualdade de um nulo através de uma consulta, veremos que NULL é diferente de NULL (ele é desconhecido).
SELECT 'Comparando'
WHERE 1 = 1
SELECT 'Comparando'
WHERE NULL = NULL
go
Então como você resolve esse problema?
- Uma abordagem seria trabalhar com triggers na tabela, garantindo a unicidade dos valores não nulos.
- Particularmente não gosto dessa abordagem, por prolongar a transação e, se necessário, efetuar um rollback da mesma.
- Poderíamos garantir a unicidade através da aplicação ou SPs, mas aí temos que garantir que ninguém vai conseguir inserir um registro "por fora".
- Essa é uma abordagem interessante por evita o rollback, mas a falta de controle e de informações para o query optimizer (como no primeiro caso) não é legal.
- Outra abordagem que mostro no treinamento, seria criarmos uma coluna computada que em combinação com a coluna original (que precisa garantir unicidade para não-nulos) deve ser única. Essa coluna computada condicionalmente recebe um valor único (o campo da PK, por exemplo) caso o campo original seja nulo ou recebe NULL caso ele não seja nulo. Dessa forma poderíamos criar uma constraint UNIQUE nas colunas original e calculada, garantindo assim a unicidade não-nula.
- Gosto dessa abordagem porque trabalhamos com constraints e não preciso confiar em terceiros para que a regra seja respeitada.
Entendeu a explicação da terceira solução? Bem, eu já li vinte vezes o que escrevi e não entendi nada, então segue um exemplo para exemplificar melhor o que eu disse. :-)
USE tempdb
go
-- Criando a tabela de teste
IF (OBJECT_ID('Funcionario') IS NOT NULL)
DROP TABLE Funcionario
go
CREATE TABLE Funcionario
(
Codigo INT IDENTITY NOT NULL,
Nome VARCHAR(200) NOT NULL,
CNPJ CHAR(14) NULL)
go
ALTER TABLE Funcionario
ADD CONSTRAINT UNQ_Funcionario_CNPJ
UNIQUE (CNPJ)
go
ALTER TABLE Funcionario
ADD CONSTRAINT PK_Funcionario
PRIMARY KEY (Codigo)
go
-- Inserts OK
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Ronaldo Fenômeno', NULL)
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Nilmar', '000.000.000-00')
go
-- Ambos os INSERTs abaixo irão trazer problema por conta da constraint UNIQUE
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Ronaldo Fenômeno 2', NULL)
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Nilmar 2', '000.000.000-00')
go
-- Reconstruindo a tabela com a coluna computada
IF (OBJECT_ID('Funcionario') IS NOT NULL)
DROP TABLE Funcionario
go
CREATE TABLE Funcionario
(
Codigo INT IDENTITY NOT NULL,
Nome VARCHAR(200) NOT NULL,
CNPJ CHAR(14) NULL,
CNPJNulo AS (CASE WHEN CNPJ IS NULL THEN Codigo ELSE -1 END)
)
go
ALTER TABLE Funcionario
ADD CONSTRAINT PK_Funcionario
PRIMARY KEY (Codigo)
go
ALTER TABLE Funcionario
ADD CONSTRAINT UNQ_Funcionario_CNPJ
UNIQUE (CNPJ, CNPJNulo)
go
-- Inserts OK
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Ronaldo Fenômeno', NULL)
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Nilmar', '000.000.000-00')
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Caio do Botafogo', '000.000.000-01')
go
-- Vai funcionar
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Ronaldo Fenômeno 2', NULL)
go
-- Não vai funcionar
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Nilmar 2', '000.000.000-00')
go
Melhorou?
Dessa forma conseguimos garantir a unicidade antes que o valor seja inserido na tabela, sem a necessidade de criação de triggers.
SQL Server 2008
Agora que vem a sacada, enquanto estava falando sobre isso o amigo Burgos me perguntou: eu não conseguiria resolver esse problema utilizando índices com filtro?
(Momento de silêncio na sala)
Caramba! Se a unicidade é garantida através de índices e eu posso criar um índice com o predicado "IS NOT NULL", então provavelmente filtered index deve resolver o problema! Testamos e bang! Na mosca.
Eu tinha ficado tão focado nos ganhos de desempenho e tamanho dos índices com filtro que nunca tinha parado para pensar nessa utilização! Nada melhor do que dar aula e aprender também = Doscendo discimus.
Vamos ao exemplo…
-- Somente para SQL Server 2008
-- Resolução com filtered indexes
IF (OBJECT_ID('Funcionario') IS NOT NULL)
DROP TABLE Funcionario
go
CREATE TABLE Funcionario
(
Codigo INT IDENTITY NOT NULL,
Nome VARCHAR(200) NOT NULL,
CNPJ CHAR(14) NULL)
go
ALTER TABLE Funcionario
ADD CONSTRAINT PK_Funcionario
PRIMARY KEY (Codigo)
go
CREATE UNIQUE NONCLUSTERED INDEX idx_CNPF
ON Funcionario (CNPJ)
WHERE CNPJ IS NOT NULL
go
-- Inserts OK
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Ronaldo Fenômeno', NULL)
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Nilmar', '000.000.000-00')
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Caio do Botafogo', '000.000.000-01')
go
-- Vai funcionar
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Ronaldo Fenômeno 2', NULL)
go
-- Não vai funcionar
INSERT INTO Funcionario (Nome, CNPJ) VALUES ('Nilmar 2', '000.000.000-00')
go
Viu que realmente funciona?!
Espero que a solução pré-SQL Server 2008 e a nova abordagem possam ajudar você no dia-a-dia.
Só fiquei agoniado com uma coisa nessa abordagem, relacionado com o Query Optimizer, mas vou fazer alguns testes e depois coloco aqui minhas considerações.
[]s
Luciano Caixeta Moreira - {Luti}
Chief Innovation Officer
Sr. Nimbus Serviços em Tecnologia Ltda - www.srnimbus.com.br
luciano.moreira@srnimbus.com.br
www.twitter.com/luticm


