2014, um MVP de SQL Server a menos, mudanças e novidades

Bom Dia Pessoal,

Após mais de um ano sem blogar resolvi dar as caras e escrever alguma coisa por aqui. Dizem que o ano só começa na primeira segunda-feira após o carnaval, pois, mesmo quinta e sexta ainda tem muitos agitos por aí Brasil a fora. Pois bem, ano de 2014 realmente começando e estou aqui escrevendo o meu primeiro post de 2014.

Puxa quanta coisa andou mudando desde o último post e nesse pequeno início de ano em 2014 e vou compartilhar a seguir algumas das coisas que aconteceram que mudaram meus planos para esse ano.

O primeiro grande acontecimento nesse ano de 2014, ou melhor, em 31/12 de 2013 foi saber que eu não renovaria o título de MVP (que boa notícia para um reveillon). Confesso que não era uma ligação que eu esperava, mas ela acabou acontecendo. O interessante é que quando você vai renovar ninguém te liga e um email chega no dia 01 do seu ciclo (sou do ciclo de janeiro) que é exatamente o dia em que você é nomeado, mas se chegar um email no dia anterior e alguém de te ligar… Ah tiro e queda e comigo não foi diferente.

No momento em que vi o email e recebi a ligação da minha MVP LEAD, eu já sabia do que se tratava e em um pequeno espaço de tempo começaram a passar mil coisas pela minha cabeça. Afinal, porque eu não consegui renovar ? Tudo bem que deixei de blogar o ano de 2013 e minha participação nos fóruns Microsoft foram reduzidas a zero, mas isso não significa que eu não tenha contribuído. Hora foram vários vídeos no youtube e mais três eventos presenciais em que palestrei (duas edições do SQL Sat e mais uma edição do Codificando .NET e todas com as devidas comprovações).

Ainda assim, poderia dizer que a decisão foi injusta ? Indignar-me por achar que eu contribui mais que fulano que fez muito menos e ainda é MVP ou beltrano que não faz nada útil e ainda mantém o título ? Puxa, o que faltou ? Será que um vídeo a mais ia garantir ? Se eu tivesse feito mais palestras eu conseguiria o pontinho que faltava ? Será que uma presença maior na redes sociais teria bastado ? Bem, passou pela minha cabeça questionar, mas como disse para a minha MVP Lead na época, aquele não era o momento para fazer lamentações apenas agradecimentos. Injustiça ? Eu só poderia dizer isso se os critérios de obtenção e manutenção fossem conhecidos, mas como não são, não posso dizer que foi injusto. O fato é que tanto a conquista e a manutenção desse título são caminhos em uma estrada que não estão claramente definidos. Apenas os seguimos com a nossa intuição e colaborações para com a comunidade e alguém nos observa para ver se continuamos na trilha certa e por alguma razão eu deixei de ser notado.

Entretanto, vejamos por outra perspectiva que possa fazer sentido para a não renovação. Quando ganhei o título de MVP, minha marca registrada eram as enormes quantidades de participações no fórum (por muito tempo fiquei entre os primeiros TOP Posters) e as postagens no blog (que na época era do Windows Live). Tinha semanas que eram mais de 200 interações no fórum (sem contar o hercúlio trabalho de moderação) e minha média de postagem era um novo post a cada duas semanas no máximo. Tanta participação me rendeu o título e sua manutenção certamente. Entretanto, depois de um tempo é difícil acompanhar esse ritmo e ainda ter tanto assuntos para postagens. Resolvi diversificar. Apostei em novas participações. Postei vários vídeos, abracei os eventos presenciais, mas praticamente abandonei o fórum e o blog e enquanto eu pensava que essa era apenas uma mudança, o tomador da decisão pode ter interpretado que eu simplesmente estava abandonando a comunidade zerando minhas contribuições com esses canais.

Eu sempre soube que um dia esse dia chegaria, mas confesso que ainda tinha esperança de renovar mais uma vez. Já estava me preparando para visitar o Campus da Microsoft no próximo MVP Summit (que sem dúvida é um dos melhores benefícios de ser MVP) com a certeza de que provavelmente seria último. Infelizmente não deu. A renovação não chegou.

Independente disso, só tenho a agradecer a todos aqueles que me ajudaram, contribuiram e estiveram comigo e a Microsoft pelo tempo em que estivesse MVP (afinal ninguém é MVP pra sempre). A ajuda às comunidades me renderam incontáveis oportunidades como profissional e como pessoa. Ajudei a conhecidos, desconhecidos e até aqueles que não sabia que havia ajudado e isso sempre me fez muito bem independente das horas e da quantidade de trabalho que isso consumia.

Tive a oportunidade de ouvir de uma pessoa no meu primeiro SQL Sat que meus posts, minhas contribuições, minhas respostas ajudaram e incentivaram essa pessoa a mudar de vida, a sair de uma condição menos favorecida a realmente conseguir um emprego e ir em frente (e um dia eu conto a história toda). Tive a oportunidade de fazer amigos incríveis e conhecer um pouco mais de cada um além do SQL Server. Fui a Nova York, fui a Seattle e estive no Campus da Microsoft, conversei com gerentes de produto e dei opiniões para as versões futuras. Fui a vários CZ, a dois TechEDs e consegui encher um auditório com mais de 300 pessoas para escutar o que eu tinha a dizer. Fiz inúmeras consultorias para várias empresas importantes aumentando em muito o skill técnico, o networking e até o trato com as pessoas. Ministrei várias turmas de MOCs aqui em Bsb (acho que treinei boa parte da cidade) e isso rendeu várias outras coisas. Recebi diversos convites de trabalhos (dentre alguns que balançaram um bocado). Tive a oportunidade de palestrar no SQL Server DF e ter ilustre visita de pessoas de SP apenas para ver uma palestra minha. Puxa, se eu for pensar na gama de oportunidades e coisas boas que aconteceram, longe de mim lamentar alguma coisa. Pelo contrário, só agradeço a Microsoft por ter me proporcionado tudo isso.

Hoje esse título não me pertence mais, mas isso não me deixa triste e nem me faz me sentir menos. Sinto-me muito bem por ter feito parte desse seleto time de profissionais e desejo que outros que igualmente contribuem com as comunidades tenham a oportunidade de usufruir dos benefícios que eu tive e abraçar as oportunidades que me apareceram. A única coisa de que me arrependo foi não ter tido tempo pra baixar todos os softwares que eu queria rs, mas minha caixa de email está muito mais vazia (e os MVPs de SQL Server sabem bem o que quero dizer hehehe).

Na vida profissional estou mais afastados dos teclados e das queries. Mudei um pouco o rumo do barco. De analista, de DBA, de técnico passei a ser líder, gestor e coordenador. Dos problemas de espaço em disco, alto processamento, queries mal feitas pra resolver e scripts T-SQL, passei a ter de lidar com pessoas, orçamentos, projetos e questões políticas mais delicadas. Enquanto eu precisava entender apenas de SQL Server e seus agregados além de um pouco de Windows, agora tenho que conhecer (ainda que superficialmente) outras tecnologias como DB2, Netezza, Data Stage, etc. Uma mudança e tanto certamente, mas posso dizer que liderar uma equipe de banco de dados tão heterogênea também é um trabalho o qual me divirto um bocado na maior parte dos momentos. Adoro ir trabalhar e gosto muito da equipe a qual faço parte e sem dúvida é um trabalho o qual aprendo muito com todos.

Essa mudança do técnico para o gerencial realmente limita muito minhas participações na comunidade já que o foco mudou e isso era uma das dificuldades de me manter tão participativo. Entretanto, isso não significa que só porque perdi o título de MVP eu não vá mais contribuir. Estou de palestra marcada no SQL Saturday 284 em POA e aguardo vocês por lá. Tentarei fazer a melhor palestra possível. Poderei expor algumas das dificuldades que tivemos em um grande projeto de BI que estamos tocando.

O ano de 2014 também começou com uma excelente novidade. No final de janeiro descobri que vou ser papai pela segunda vez. Essa foi a primeira e talvez melhor notícia, pois, já era algo que estava planejando e aconteceu. Claro que na hora a gente fica assustado, mas que bom que aconteceu. Quem já é pai sabe a canseira que dá e os desafios que são, mas sem dúvida uma responsabilidade que rende boas alegrias e certamente muda tudo.

Também aproveitei esse ano para colocar em prática um hobby que eu havia deixado de lado tinha um tempão. Na minha adolescência, eu era fascinado por música eletrônica e atuei com DJ tocando em festas (e até cheguei a ser residente em uma boate). Épocas muito boas e sem dúvida estar mixando é terapia pra mim. Por que não retomar (ainda que apenas para ouvir meus próprios trabalhos) ? Já estou produzindo alguns SETs e compartilhando-os no soundcloud e no mixcloud pelos links http://soundcloud.com/gmasets e http://mixcloud.com/gmasets inclusive com as últimas compilações do fim de semana. Quem quiser aproveitar, blogar, comentar ou repassar será bem vindo.

Começo então 2014 por aqui. Obrigado a todos pelo carinho e vamos em frente.

[ ]s,

Gustavo

Introdução aos índices em bancos de dados e no SQL Server

Boa noite pessoal,

Finalizando o ano de 2012, estou aqui postando meu último artigo desse ano. Hoje finalizei a edição do último vídeo de um conjunto de quatro vídeos explicando o que são índices, para que servem, sua estrutura interna entre outros aspectos.

Iniciei a elaboração desses vídeos pensando na dificuldade que é ter explicar o que são índices em curto período de tempo nos momentos como MCT, no desafio que é explicar a diferença entre índices clustered e nonclustered em sucessivas dúvidas em fórum e principalmente para montar um material de referência que sirva para detalhar melhor algumas das explicações que vejo por aí além de desmitificar alguns equívocos que vejo por aí a citar:

“Imagine uma árvore, a organização dos indices é semelhante a um formato de árvore, na estrutura da árvore os dados das tabelas resídem no nível folha, ou seja, imagine os dados espalhados por todas as folhas da árvore, para facilitar a busca nestas folhas é que existem os índices.”

“O índice Clustered, geralmente é definido juntamente com a chave primária da tabela. Uma característica importante deste tipo de indice é que ele determina a ordem da gravação (ordenação física) dos registros.”

Independente de certas ou erradas, são afirmações que dizem muito pouco ou praticamente nada para quem ainda não tenha sido apresentado ao assunto. Assim sendo, para aqueles que desejam uma introdução mais sólida sobre o assunto de forma a montar uma boa base para aprofundá-lo e ter argumentos em discussões futuras eu recomendo dar uma olhada nos vídeos abaixo:

Índices – Fundamentos, Estruturas & Usabilidade (Parte 1)

Índices – Fundamentos, Estruturas & Usabilidade (Parte 2)

Índices – Fundamentos, Estruturas & Usabilidade (Parte 3)

Índices – Fundamentos, Estruturas & Usabilidade (Parte 4)

Elogios, sugestões e críticas são muito bem vindas. Não deixe de comentar para que eu possa evoluí-los. No resto mais, um ótimo 2013 a todos.

[ ]s,

Gustavo

Índices e Foreing Keys

Boa Noite Pessoal,

Hoje vi uma dúvida interessante no fórum de SQL Server (MSDN / TechNET). A dúvida em si não era complicada. Bastava apenas identificar quais foreign keys estavam com índices criados ou não. Postarei um script para fazer isso logo mais, mas antes de propriamente apresentá-lo parei um pouco para pensar a respeito dessa necessidade. Se alguém deseja identificar quais FKs não tem índice é porque certamente pretenderá criar índices sobre elas, o que me remete a pensar se indexar todas as FKs é de fato um bom negócio. Sim, vejo muitas recomendações para fazê-lo em vários livros de performance e modelagem de dados. De fato, costuma ser uma boa coisa em muitas situações, mas se fosse bom sempre, então porque o SQL Server, o ORACLE, o DB2 e todos os outros não criam a FKs indexadas por padrão ?

Por que criar índices sobre Foreign Keys ?

A partir do momento em que uma FK é criada sobre uma coluna ou um grupo de colunas, é impositivo que essa coluna ou esse grupo possui um relacionamento com uma coluna ou grupo de colunas de outra tabela que possui essa coluna ou grupo compondo a chave primária. Uma vez que esse relacionamento é construído por essas constraints, em algum momento será necessário identificá-lo para montar as consultas e as junções (JOINs), para recuperar um determinado resultado que combine dados de duas ou mais tabelas.

As operações de JOIN de um ponto de vista sintático são bem conhecidas (INNER, OUTER, FULL, NATURAL, etc), mas fisicamente falando, elas costumam obedecer três algoritmos básicos (Nested Loops, Merge Join e Hash Join). Não vou explicar os algoritmos hoje, mas limito a dizer que não existe um melhor ou pior que o outro (embora alguns jurem que HASH JOIN não é uma boa coisa), apenas que o otimizador normalmente sabe quando é melhor utilizar um ou outro algoritmo em uma determinada situação. O fato é que a presença de índices pode auxiliar o otimizador na escolha desse algoritmo e por consequência retornar os dados mais rapidamente. Vejamos um rápido exemplo:

— Retira a nulabilidade
SET ANSI_NULL_DFLT_OFF ON

— Cria as tabelas
CREATE TABLE Pessoas (ID INT, Nome VARCHAR(50))
CREATE TABLE Saldos (DataSaldo DATE, IDPessoa INT, Valor SMALLMONEY, HashRegistro UNIQUEIDENTIFIER)

— Cria as constraints
ALTER TABLE Pessoas ADD PRIMARY KEY (ID)
ALTER TABLE Saldos ADD PRIMARY KEY (DataSaldo, IDPessoa)
ALTER TABLE Saldos ADD FOREIGN KEY (IDPessoa) REFERENCES Pessoas (ID)
ALTER TABLE Saldos ADD DEFAULT NewID() FOR HashRegistro

— Insere alguns registros de pessoas
INSERT INTO Pessoas VALUES
(1,‘Vinicius’),(2,‘Wagner’),(3,‘André’),(4,‘Gilson’),(5,‘Emerson’)

— Insere vários registros fictícios de saldos
;WITH Nums (Num) As (
    SELECT 0 As Num
    UNION ALL SELECT Num + 1 FROM Nums
    WHERE Num < 4500)

INSERT INTO Saldos (DataSaldo, IDPessoa, Valor)
SELECT DATEADD(d,N1.Num,‘2000-01-01’) As Data, N2.Num + 1 As IDPessoa, 1000 As Valor
FROM Nums As N1
CROSS JOIN Nums As N2
WHERE N2.Num <= 2
ORDER BY Data, IDPessoa
OPTION (MAXRECURSION 0)

— Insere um registro de saldo
INSERT INTO Saldos VALUES (‘2012-08-15’,4,5000, NEWID())

— Cria um índice sobre a coluna IDPessoa na tabela Saldos
CREATE INDEX IX_Pessoa ON Saldos (IDPessoa)

Agora que a tabela está criada, vejamos uma consulta que traga o nome e os registros de saldo do primeiro cliente:

SELECT P.Nome, S.* FROM Pessoas As P
INNER JOIN Saldos As S ON P.ID = S.IDPessoa
WHERE P.ID = 4

O plano de execução é exibido logo abaixo:

Índices e Foreign Keys (Index Seek)

Podemos ver que primeiro o índice IX_Pessoa foi utilizado para pesquisar os registros na tabela de Saldo com IDPessoa = 4 retornando um ponteiro para o único registro existente na tabela de Saldos com essa condição. Posteriormente, após achar os ponteiros no índice, foi feita uma operação de Lookup contra a tabela Saldos e a junção do ponteiro do índice IX_Pessoa com os registros foram consolidadas em uma operação de junção através do algoritmo Nested Loop. Para juntar os registros da tabela de pessoas com a tabela de Saldos, foi feita uma outra operação de JOIN através do algoritmo Nested Loops e por fim o resultado foi devolvido (muito rapidamente por sinal). Podemos ver que nesse caso, o uso do índice foi muito benéfico para acelerar a pesquisa e o resultado corrobora com a tese de que indexar FKs é uma boa idéia.

Uma segunda opinião

E se mudássemos a consulta ? E se ao invés de escolher IDPessoa = 4 escolhéssemos IDPessoa = 1 ? Vejamos:

SELECT P.Nome, S.* FROM Pessoas As P
INNER JOIN Saldos As S ON P.ID = S.IDPessoa
WHERE P.ID = 1

O plano de execução é exibido logo abaixo:

Índices e Foreign Keys (Clustered Index Scan)

Dessa vez os resultados foram um pouco diferentes da consulta anterior. Podemos ver que na tabela Pessoa, houve uma pesquisa (Seek) para recuperar a pessoa de ID = 1, mas na tabela Saldos, houve uma varredura (Scan) da tabela inteira (Clustered Index pq ela está clusterizada). O otimizador concluiu que era melhor ignorar o índice IX_Pessoa, pois, para favorecer a condição IDPessoa = 1, seria mais fácil ler a tabela inteira do que ir no índice e ir na tabela registro a registro. Se formos analisar por esse resultado, a criação de índices em FKs só tem a trazer desvantagens. O índice IX_Pessoa na tabela de saldos irá retardar as operações de escrita, irá ocupar mais espaço e não servirá para atender as consultas que utilizem a coluna IDPessoa. No entanto, será que o índice não serve mesmo para nada ?

SELECT P.Nome, COUNT(*) FROM Pessoas As P
INNER JOIN Saldos As S ON P.ID = S.IDPessoa
WHERE P.ID = 1
GROUP BY P.Nome

O plano de execução é exibido logo abaixo:

Índices e Foreign Keys (GROUP BY)

Embora o índice IX_Pessoa não seja útil para filtrar registros na tabela Saldos onde IDPessoa = 1, o fato de existir um índice  e o objetivo ser apenas uma contagem e não uma exibição das colunas, faz com que a consulta tenha de ser feita apenas sobre o índice e nesse caso, foi possível até fazer um seek e posteriormente uma agregação para posteriormente efetuar um JOIN com a tabela Pessoas. Podemos ver que o índice IX_Pessoa não é tão ruim afinal.

O papel do índice em relacionamentos fortes ou identificados

Um relacionamento é caracterizado pela presença de uma PK em sua tabela Pai e uma FK referenciado as colunas da PK em uma tabela filha. Diz-se que o relacionamento é forte ou identificado quando as colunas da FK também fazem parte da PK na tabela filha. Vejamos o papel que o índice pode desempenhar nesse caso.

— Efetua duas cópias da tabela de Saldos
SELECT IDPessoa, DataSaldo, Valor, HashRegistro
INTO Saldos2 FROM Saldos
ORDER BY IDPessoa, DataSaldo

SELECT IDPessoa, DataSaldo, Valor, HashRegistro
INTO Saldos3 FROM Saldos
ORDER BY IDPessoa, DataSaldo

— Cria as constraints (PK apenas em Saldos2)
ALTER TABLE Saldos2 ADD PRIMARY KEY (IDPessoa, DataSaldo)
ALTER TABLE Saldos2 ADD FOREIGN KEY (IDPessoa) REFERENCES Pessoas (ID)
ALTER TABLE Saldos3 ADD FOREIGN KEY (IDPessoa) REFERENCES Pessoas (ID)

— Cria um índice em Saldos3
CREATE INDEX IX_Pessoa ON Saldos3 (IDPessoa)

Agora vejamos o impacto nas consultas que fizemos anteriormente:

SELECT P.Nome, S.* FROM Pessoas As P
INNER JOIN Saldos2 As S ON P.ID = S.IDPessoa
WHERE P.ID = 1

SELECT P.Nome, S.* FROM Pessoas As P
INNER JOIN Saldos3 As S ON P.ID = S.IDPessoa
WHERE P.ID = 1

O plano de execução é exibido logo abaixo:

20120815_04_FK

No primeiro caso, podemos ver que o fato da coluna IDPessoa ser a primeira coluna da chave primária (que por padrão é clusterizada) faz com que a leitura dos registros da tabela Saldos2 ainda seja uma pesquisa (Seek), pois, a chave primária composta por IDPessoa e DataSaldo impõe uma ordem dos registros por IDPessoa. Já no caso da tabela Saldos3, como não há nenhuma ordem e muitos registros para IDPessoa = 1, o índice é simplesmente ignorado e a tabela é completamente varrida (Table Scan). Proporcionalmente, podemos ver que a consulta em Saldos3 é duas vezes maior que em Saldos2 (67% vs 33% no mesmo Batch).

O papel do índice nas operações de exclusão

Até agora tivemos um foco muito grande no uso do índice nas FKs para consultas, mas ele tem papel nas operações de exclusão ou atualizações em cascata ?

— Efetua uma cópia da tabela de Saldos
SELECT * INTO Saldos4 FROM Saldos

— Cria as constraints
ALTER TABLE Saldos4 ADD PRIMARY KEY (DataSaldo, IDPessoa)
ALTER TABLE Saldos4 ADD FOREIGN KEY (IDPessoa) REFERENCES Pessoas (ID)

DELETE FROM Pessoas WHERE ID = 1

O plano de execução é exibido logo abaixo:

Índices e Foreign Keys (Exclusões)

Podemos ver que a exclusão ocorre na tabela Pessoas representada pela operação Clustered Index Delete. Também podemos ver que é feita uma verificação da existência de registros filhos nas tabelas Saldos, Saldos2, Saldos3 e Saldos4. Podemos ver que em todas as tabelas filhas é feita uma pesquisa para checagem da existência (algo muito parecido com a consulta que fez a contagem de registros nos exemplos anteriores). Especificamente na Saldos4, podemos ver que é feita uma varredura.

Índices e Foreign Keys (Exclusões)

A varredura na tabela Saldos4 é feita porque não há como saber se existem registros para IDPessoa = 5 senão lendo a tabela inteira uma vez que não exista nenhum índice capaz de auxiliar nessa pesquisa. Em virtude da tabela ser pequena, o custo no plano é de apenas 13% (1% a mais do que as demais tabelas de Saldo). Agora imagine se essa tabela fosse muito grande e muito larga. Uma varredura poderia tornar a exclusão absurdamente lenta, além de impor bloqueios por muito tempo e muitas vezes desnecessários.

Algumas conclusões

A conclusão que chego é provavelmente a que os fabricantes já chegaram, ou seja, como não sabemos o comportamento da seletividade dos valores nas colunas da chave estrangeira, não há como afirmar se a criação de índices em chaves estrangeiras é ou não um bom negócio. Então nesse caso, é melhor assumir a posição de não criar índices nas colunas das chaves estrangeiras e deixar a cargo do implementador efetuar essa avaliação. Excetuando as operações de exclusão e atualizações em cascata, a criação de índices está muito mais voltada para a consulta em si do que o fato de existir um relacionamento. Ainda assim algumas recomendações:

  1. Se você for efetuar exclusões nas tabelas pai com frequência e as tabelas filhas forem muito volumosas, indexe as FKs
  2. Se você for efetuar JOINs com o objetivo apenas de contar registros ou verificar existência (EXISTs), indexe as FKs
  3. Se você utilizar relacionamentos fortes ou identificados, indexe as FKs
  4. Se as ocorrência dos valores nas colunas das FKs tiverem muita repetição, ou seja, forem pouco seletivas e as condições acima não forem verdadeiras, avalie se criar índices é um bom negócio (possivelmente não será)
  5. Se os três primeiros itens não forem verdadeiros, olhe a criação do índice muito mais como um índice sobre um coluna comum, pois, nesse caso, a coluna ser ou não FK não fará diferença

E como descobrir quais FKs não estão indexadas ?

Seria simples utilizar o exemplo anterior que possui colunas simples, mas vou criar mais três tabelas com chaves compostas e assim podermos avaliar a eficácia do meu script. Embora as tabelas induzam um relacionamento identificado, deixarei algumas colunas de fora propositalmente

— Retira a nulabilidade
SET ANSI_NULL_DFLT_OFF ON

— Cria mais três tabelas
CREATE TABLE SaldosSuspeitos (DataSaldo DATE, IDPessoa INT, DataInclusao DATE)
CREATE TABLE SaldosLimite (DataSaldo DATE, IDPessoa INT, DataInclusao DATE)
CREATE TABLE SaldosDevedores (DataSaldo DATE, IDPessoa INT, DataInclusao DATE)

— Adiciona as Constraints
ALTER TABLE SaldosSuspeitos ADD PRIMARY KEY (DataSaldo, IDPessoa)
ALTER TABLE SaldosSuspeitos ADD FOREIGN KEY (DataSaldo, IDPessoa) REFERENCES Saldos (DataSaldo, IDPessoa)
ALTER TABLE SaldosLimite ADD FOREIGN KEY (DataSaldo, IDPessoa) REFERENCES Saldos (DataSaldo, IDPessoa)
ALTER TABLE SaldosDevedores ADD FOREIGN KEY (DataSaldo, IDPessoa) REFERENCES Saldos (DataSaldo, IDPessoa)

— Adiciona um índice na FK para a tabela SaldosDevedores
CREATE INDEX IX_Saldo ON SaldosDevedores (DataSaldo, IDPessoa)
CREATE INDEX IX_DataSaldo ON SaldosLimite (DataSaldo)

Visualmente sabemos que a tabela Saldo4 não tem índice na coluna IDPessoa e tem FK para essa coluna. Sabemos também que a tabela SaldosLimite tem a FK com as colunas DataSaldo e IDPessoa, mas possui um índice apenas sobre a coluna DataSaldo e portanto não tem sua FK indexada. Segue a consulta:

;WITH FKsNI (ObjectId, FKId) As (
SELECT DISTINCT
    parent_object_id, constraint_object_id
FROM sys.foreign_key_columns As FC
WHERE NOT EXISTS (
    SELECT * FROM sys.index_columns As IC
    WHERE
        FC.parent_object_id = IC.object_id AND
        FC.constraint_column_id = IC.index_column_id AND
        FC.parent_column_id = IC.column_id))

SELECT
    OBJECT_NAME(FKsNI.ObjectId) As Objeto,
    OBJECT_NAME(FKsNI.FKId) As FK,
    C.Name As Coluna,
    FC.constraint_column_id As Ordem
FROM FKsNI
INNER JOIN sys.foreign_key_columns As FC ON
    FKsNI.FKId = FC.constraint_object_id AND
    FKsNI.ObjectId = FC.parent_object_id
INNER JOIN sys.columns As C ON
    FC.parent_object_id = C.object_id AND
    FC.parent_column_id = C.column_id
ORDER BY Ordem

O resultado sai exatamente conforme o esperado:

Objeto FK Coluna Ordem
Saldos4 FK__Saldos4__IDPesso__25869641 IDPessoa 1
SaldosLimite FK__SaldosLimite__2B3F6F97 DataSaldo 1
SaldosLimite FK__SaldosLimite__2B3F6F97 IDPessoa 2

Agora vem a pergunta ? Depois que você rodar a consulta e identificar as FKs que não estão indexadas, você vai criar os índices ? Depende de cada um.

[ ]s,

Gustavo

WEBCAST – Concorrência de dados no SQL Server (depois da apresentação)

Bom Dia Pessoal,

Hoje faz uma semana que fiz a apresentação do webcast “Concorrência de dados no SQL Server”. Já tinha um tempinho que eu não fazia apresentações e deixando alguns apertos (microsoft, atualização do live meeting, vms, etc) consegui iniciá-lo sem problemas (um leve atraso de dez minutos).

Foram praticamente duas horas de apresentação e terminamos um pouco depois das 23h e eu estava sem a água do lado, mas correu tudo bem. Eu não consegui ver a lista de participantes (apenas dei um rápida visualizada, mas não deu pra memorizar). De qualquer forma eu agradeço a todos que acompanharam (Crespi, Raionan, Sulamita eu vi vocês lá). Também agradeço ao Felipe e a Andressa pelo suporte e espero poder apresentar em situações futuras (se o tempo permitir).

Nos bastidores, foi um webcast difícil de montar. Se pesquisar o funcionamento dos outros SGBDs como o Oracle e o DB2 já é difícil, se simular o efeito do Double Reads gastou metade de uma madrugada (até DEADLOCK no SELECT eu consegui), o que realmente deu trabalho foi fazer o PPT animado. Enfim, foi trabalhoso, mas faço de bom grado para a comunidade. Críticas e sugestões são bem vindas (não deu tempo no Webcast).

Aos que não puderam assistir não tem problema. Acredito que o time do Virtual Pass irá disponibilizar a palestra em breve, mas eu já me antecipei e coloquei a palestra no meu canal do Youtube (em vídeos picados). A quem se interessar, segue o link:

Concorrência de Dados
http://www.youtube.com/playlist?list=PL70D92D06E08E6653&feature=plcp

Aos que desejarem os scripts e a base utilizados, vocês podem obter em:

http://cid-f4f5c630410b9865.office.live.com/self.aspx/ProjetosSQLServer/20120322_Concorrencia.rar

Só não entendi porque o Camtasia deu um zoom indesejado em algumas partes do vídeo, mas enfim… Espero que não ocorra na próxima. Agora é preparar o PPT do SQL Saturday 127.

[ ]s,

Gustavo

SQL Saturday 127 – Rio de Janeiro aí vou eu

Oi Pessoal,

Há alguns dias recebi a grata notícia de que serei um dos palestrantes do SQL Saturday 127 que irá ocorrer no dia 14/04. Não preciso nem dizer que fiquei feliz com a oportunidade de estar novamente tão próximo da comunidade levando um pouco da vivência, dos apertos, dos erros e da experiência com o produto. O formato presencial me agrada muito, pois, me lembra a sala de aula nos momentos de MCTs, mas de uma forma mais aberta sem as restrições do MOC ou imposição de temas. O SQL Saturday 100 foi excelente e se o 127 for na mesma linha será um grande evento.

Na minha sessão falarei sobre o processo de ETL e algumas técnicas para escalá-lo de forma incremental e alternativas no SQL Server para processos ETL Near Real Time. O foco será mais forte no SQL Server, mas algumas técnicas são independentes de SGBD. Atualmente estou participando nas definições de infraestrutura de um grande projeto de Business Intelligence e embora BI não seja o meu maior foco de atuação, essa experiência está sendo bem engrandecedora. As definições de uma infraestrutura de BI dependem naturalmente da arquitetura da solução e o contato com arquitetos, consultores, desenvolvedores de ETL, etc é natural. É um excelente aprendizado no qual eu pretendo compartilhar um pedacinho nesse evento (se o tempo permitisse a gente falava por horas).

Será um sábado inteiro de SQL Server e se você é entusiasta do produto, trabalha com ele ou depende dele de alguma forma, essa é sem dúvida uma ótima oportunidade, até porque o evento é gratuito e as vagas são limitadas. Se você pretende participar, não deixe de obter mais informações no site oficial do evento em: http://www.sqlsaturday.com/127/eventhome.aspx

A agenda do evento está com muito boas palestras e naturalmente algum conflito irá acontecer durante as escolhas (eu mesmo tive muita dificuldade). Eis a minha escolha pessoal:

  • 09:15 – Marcelo Sincic – Dimensionando Hardware e Storage para SQL Server
  • 11:15 – Diego Nogare – Pontapé inicial de Business Intelligence na Nuvem
  • 14:15 – Gustavo Maia Aguiar – Algoritmos e alternativas para cargas incrementais
  • 16:15 – Felipe Ferreira – Melhores práticas para o seu Data Warehouse

Claro que também é uma excelente oportunidade para encontrar alguns dos vários conhecidos da comunidade de SQL Server bem como conhecer aqueles que ainda não tive a oportunidade. Então anote aí na agenda. Dia 14/04 é dia de SQL Saturday.

Espero vê-los por lá.

[ ]s,

Gustavo

WEBCAST – Concorrência de dados no SQL Server

Olá Pessoal,

Começando a colocar os planos de SQL Server no ano 2012 em ação e a iniciativa de apostar um pouco mais em vídeo nesse ano, estou indo para mais uma gravação.

O VirtualPassBR está com uma iniciativa de transmitir WebCasts todas as terças e quintas e tive o prazer de ser convidado para fazer o primeiro de uma série de eventos que virão.

No dia 15 desse mês, falarei sobre concorrência em banco de dados com um foco maior no SQL Server embora deva dar algumas palavrinhas sobre esse assunto em outros SGBDs. O assunto realmente me desperta bastante interesse.

A concorrência é cruel

Entender a concorrência por dados é peça na chave na construção de aplicações que possam escalar. Meia dúzia de usuários podem conviver mesmo que a aplicação tenha erros, mas dificilmente veremos um grande banco transacionando sem nos atentarmos para o assunto concorrência. Infelizmente há muitos implementadores que desconhecem esse assunto e confiam na mão invisível (o Adam Smith do banco) ou apelam para o NOLOCK. Pretendo explorar um pouco mais assunto e tentarei cobrir essas brechas.

Falarei dos principais problemas envolvidos em situações concorrentes, os modelos de concorrência, os níveis de isolamento e algumas situações que acompanho no fórum.

Se você deseja conhecer um pouco mais sobre esse assunto faça já a inscrição clicando aqui. Vejo vocês por lá.

[ ]s,

Gustavo

Iniciando 2012

Olá Pessoal,

Dizem que o ano só começa efetivamente depois do carnaval. Eu gostaria de ser um dos felizardos que pode dizer isso (alguém aí pode ?), mas não é o caso. De fato apenas hoje após alguns dias do término do carnaval, estou conseguindo colocar o meu primeiro post. Desde que comecei a me preparar para palestrar para o TechED 2011 que não consegui parar. Tanto esforço rendeu um bom feedback, pois, as avaliações do TechED foram muito satisfatórias para minha primeira apresentação em um evento desse porte. Na cola nem deu tempo de descansar, pois, iniciou-se a preparação para o SQL Saturday na sua edição de número 100 aqui no Brasil. Evento fantástico onde tive a oportunidade de conhecer e fazer novas amizades além de reencontrar as já existentes. Eu realmente adoro iniciativas com a comunidades, pois, não há nada mais gratificante do que ver a vontade em compartilhar alcançar lugares que nem mesmo imaginávamos. Na lista desses eventos entraram ainda o MVP Open Days e o Community Zone que também são excelentes oportunidades, mas consomem um pouquinho.

Pensei que depois do SQL Saturday eu iria diminuir o ritmo, mas no meu ambiente atual, acabei tendo uma baixa de um dos melhores DBAs da minha equipe e aí e passei a dar mais de mim para compensar essa baixa que espero resolver o quanto antes. Para piorar, coloque um pequeno problema de saúde e aí de fato, posso dizer que já tem algum tempo que eu não parava mesmo e ainda sem estar por aqui.

Pois bem, felizmente, depois de quase 30 dias de férias (como é bom poder tirar tanto tempo de férias e viajar ainda por cima) e praticamente ausente de emails, MSN, blogs, comunidades e iniciativas SQL Server estou de volta. Começando o ano de 2012 ainda um pouco devagar (estamos apenas alguns dias depois da quarta-feira de cinzas), estou com as baterias recarregadas e pronto para contribuir. Os anos de 2008 e 2009 dediquei praticamente 100% ao fórum e ao blog e alguns Webcasts. A partir de 2009, já comecei a utilizar outros tipos de canais como artigos técnicos para revistas, mas apenas em 2011 realmente diversifiquei. Além das palestras presenciais (que gostei muito de fazer), consegui gravar vídeos para o Centro de Treinamento de SQL Server, fazer um WebCast para o Virtual Pass e ainda colocar os vídeos no meu canal no Youtube.

Esse ano eu pretendo investir mais nesse tipo de iniciativa. Não que eu não queira ou não vá continuar blogando ou respondendo threads nos fóruns do MSDN e do Technet, mas é que vejo um alcance muito interessante em outros canais e pretendo explorá-los um pouco mais e não me restringir somente aos mais tradicionais.

Para iniciar acabei de postar o primeiro vídeo de uma coleção que pretendo postar abordando diversos assuntos sobre SQL Server e banco de dados. Os primeiros vídeos serão focados no assunto indexação e pretendo fazer uma introdução bem detalhada no assunto sem naturalmente a prentensão de esgotá-lo.

É nesse ponto e com esse vídeo que começo 2012. Vejamos o que consigo fazer  e até onde ir para ajudar essas pessoas. Feedbacks e sugestões de temas são bem vindos.

[ ]s,

Gustavo