Resultados de busca
243 resultados encontrados com uma busca vazia
- Dataside participa do SQL SAT 804 em São Paulo
No último sábado, 29 de Setembro, a equipe Dataside marcou presença no SQL SAT 804. O evento aconteceu em São Paulo e contou com palestras e capacitação para profissionais do SQL Server. Nossos #dataholics palestraram sobre diferenças de arquitetura entre Relacionais e NoSQL, Event Hub + Stream Analytics Jobs + Power BI = Visualizando dados em tempo real e Let’s talk about Always on Availability Group. Além disso, a Dataside foi patrocinadora oficial do evento. Para o MVP Caio Amante participar do SQL SAT é sempre importante “Para nós, o SQL SAT é um evento muito significativo dentro da comunidade Data, lá trocamos experiências, contatos e podemos falar um pouco mais sobre os serviços oferecidos pela nossa empresa” diz. A equipe Dataside agradece o convite e a presença de toda a comunidade que está sempre procurando crescer através de nossas palestras!
- Dataside irá marcar presença no SQL SAT 804 em São Paulo
Os nossos #Dataholics estão confirmados em mais um evento. Desta vez, iremos participar do SQL SAT 804 em São Paulo no dia 29 de Setembro. O SQLSaturday é um evento de capacitação para profissionais de SQL Server, Business Intelligence e aqueles que querem aprender sobre o universo da Plataforma de dados da Microsoft. O SQL SAT contará com três palestrantes da equipe Dataside: Nosso MVP Caio Amante irá falar sobre as diferenças de arquitetura entre Relacionais e NoSQL; Reginaldo Silva vai palestrar sobre Event Hub + Stream Analytics Jobs + Power BI = Visualizando dados em tempo real, e Jéssica Lima junto com Marcus Bittencourt ministram a Let’s talk about Always on Availability Group. Além de palestrante, a Dataside também é patrocinadora oficial do evento! Mais informações: – Data: 29 de Setembro de 2018 – Local: UNIP Tatuapé, Rua Antônio Macedo, 505 – Parque São Jorge, Tatuapé – São Paulo – SP, – Inscrições: https://www.sqlsaturday.com/804/EventHome.aspx
- Profissionais da Dataside marcaram presença em eventos no fim de semana
Nos dias 13 e 15, a Dataside marcou presença em eventos no Vale do Paraíba e em Minas Gerais. No dia 13 de Setembro, aconteceu o 4º Encontro do local group SQL Vale em São José dos Campos. Neste encontro, nossos #Dataholics Caio Amante e Reginaldo Silva palestraram sobre as diferenças de arquitertura entre bancos relacionais e NoSQL. O Encontro ainda contou com feras da comunidade técnica como o Leandro Domingues, Heber Lopes e o nosso também #Dataholic, Igor de Paula. Fomos direto para Minas Gerais, onde nosso time marcou presença no auditório da MaxMilhas em Belo Horizonte para o Zero to Hero, o maior evento de NoSQL e Azure Cosmos DB da atualidade. A Dataside também foi patrocinadora oficial deste mega evento. Em nome de todos os nossos #Dataholics, agradecemos à comunidade que está cada vez mais engajada, lotando os auditórios para nossas palestras. Confira um pouco mais de como foi nossa participação nestes eventos! #valedoparaiba #minasgerais #dba #zerotohero #evento #sqlvale
- Conhecendo o Plan Guide
Por Caio Amante Olá pessoal! Eu sou Caio Amante e quero iniciar meus posts técnicos já escrevendo de algo que em regras gerais, poucas pessoas conhecem e principalmente utilizam. O plan guide, este nosso “amigo”, foi introduzido no SQL Server 2005 e tem como principal objetivo forçar um determinado comportamento para uma query, objeto e até mesmo a um conjunto de querys. Eu sei que a partir do SQL Server 2016, temos um “cara” chamado QUERY STORE, que além de muito intuitivo, resolve muitos dos aspectos relacionados a melhorias em planos de execução, no entanto, acredito que ele não substitui por completo o plan guide, provando assim, sua utilidade. Existem diversos casos onde o dba necessita refinar determinados processos e não possui acesso ao código-fonte da aplicação para efetuar as devidas alterações, isto é comum principalmente em ERP’s como: Protheus, SAP, RM e outros. É sabido por muitos que na maioria dos casos o otimizador de consulta escolhe os melhores caminhos para execução das querys, no entanto existem casos específicos que nós (dbas), realmente queremos influenciar no comportamento de determinado código SQL. Apesar de introduzido SQL Server 2005, como já citado, o plan guide recebeu suas principais melhorias na versão 2008 e basicamente tem sua funcionalidade em permitir que hints sejam forçadas em querys sem que seja necessária a mudança no código fonte da aplicação. A funcionalidade está disponível nas edições Standard, Developer e Enterprise. Vamos entender melhor o que é e como funciona logo na sequência. Existem três tipos de plan guide no SQL Server e iremos adentrar por cada um deles, mas antes iremos mostrar os principais parâmetros existentes e explicar suas funções. @name: É o nome do plan guide @stmt: A consulta a qual deve ser otimizada @type: O tipo do plan guide, podendo ser um objeto, um SQL ou mesmo do tipo template. @modulo_or_batch: O nome da procedure ou function, caso seja do tipo objeto, do contrário este campo ficará nulo. @params: parâmetros definidos na sentença, usados para templates. @hints: São hints de query e tabela que queremos forçar o sql. Sumário SQL PLAN GUIDE OBJECT PLAN GUIDE TEMPLATE PLAN GUIDE Gerenciamento de Plan guide Considerações sobre Plan guide SQL PLAN GUIDE O primeiro tipo que iremos abordar aqui é o de uma sentença SQL sem estar encapsulada em nenhum objeto como procedure, trigger ou mesmo uma function, este é chamado de SQL plan guide. Imagine um código SQL isolado (ad-hoc), talvez um statement enviado por um SQL Server CLR ou parte de uma query dinâmica chamada com EXEC (sql_string). Neste caso o @modulo_or_batch para a procedure sp_create_plan_guide precisa ser informado como NULL, desta forma o SQL SERVER assume que a batch e a sentença possuem o mesmo valor. Vamos criar um cenário para deixar nosso aprendizado mais transparente ok? Cenário: Identificamos uma determinada query ativando paralelismo e isto está causando problemas em outros processos do banco de dados. Abaixo a query: SELECT TOP 1 * FROM Sales.SalesOrderHeader ORDER BY OrderDate DESC; Digamos que esta query seja executada o dia todo, que o paralelismo esteja sendo ativado e necessitamos de alguma forma diminuir o uso de paralelismo no servidor, principalmente nesta query, porém este código vem diretamente de uma aplicação onde o código fonte “se foi” junto com o programador, rs… quem nunca passou por isto? Teoricamente como poderíamos resolver esta situação? Query Store? Nãooo!! O Plan guide se encaixa perfeitamente neste cenário, onde identificamos e precisamos controlar uma operação de um banco de dados, basicamente ele permite que sejam realizados ajustes finos em determinadas sentenças SQL. Neste caso, forçar esta query a utilizar apenas um processador. EXEC sp_create_plan_guide @name = N’plan_SalesOrderHeader_DOP1′, @stmt = N’SELECT TOP 10 * FROM Sales.SalesOrderHeader ORDER BY OrderDate DESC’, @type = N’SQL’, @module_or_batch = NULL, @params = NULL, @hints = N’OPTION (MAXDOP 1)’; Como é possível visualizar, executamos uma procedure chamada sp_create_plan_guide, onde informamos os parâmetros referentes ao processo que gostaríamos de mudar o comportamento do SQL Server. A partir de agora ao executarmos o mesmo comando processado inicialmente, teremos um plano de execução sem paralelismo, forçamos essa condição utilizando o plan guide. SELECT TOP 1 * FROM Sales.SalesOrderHeader ORDER BY OrderDate DESC; Este foi um exemplo simples utilizando uma query ad-hoc do dia-dia, no entanto, existem outros casos em que podemos utilizar o plan-guide para nos auxiliar. OBJECT PLAN GUIDE O tipo object de plan guide está relacionado a um statement_text, que está vinculado a uma procedure, uma function ou mesmo uma trigger dml. Ele é utilizado quando se torna necessária a mudança do comportamento de uma sentença, pertencente a um determinado objeto, desta forma na criação do plan guide, além de colocarmos a sentença, também colocamos o objeto que a mesmo pertence. Assim como anteriormente, iremos montar um cenário para entendermos melhor como funciona esta opção. Cenário: Identificamos que o plano de execução em uma determinada query tem variado muito e queremos forçar o plano baseando-se em um filtro (que em geral) traz uma performance adequada para a maioria das variações de parâmetro. IF OBJECT_ID(N’Sales.GetSalesOrderByCountry’, N’P’) IS NOT NULL DROP PROCEDURE Sales.GetSalesOrderByCountry; GO CREATE PROCEDURE Sales.GetSalesOrderByCountry (@Country_region nvarchar(60)) AS BEGIN SELECT * FROM Sales.SalesOrderHeader AS h INNER JOIN Sales.Customer AS c ON h.CustomerID = c.CustomerID INNER JOIN Sales.SalesTerritory AS t ON c.TerritoryID = t.TerritoryID WHERE t.CountryRegionCode = @Country_region; END GO Esta procedure acima mostra a query que iremos implementar o plan guide, onde a mesma recebe um parâmetro de entrada, ou seja, este é o nosso objeto. Vamos executar a procedure com o parâmetro “FR” para verificar como o SQL Server irá se comportar: DBCC FREEPROCCACHE EXEC [Sales].[GetSalesOrderByCountry] @Country_region = ‘FR’ A execução com o filtro ‘FR’ utilizou o plano de execução demonstrado anteriormente. Vamos verificar o plano para a mesma execução de procedure com outro parâmetro. DBCC FREEPROCCACHE EXEC [Sales].[GetSalesOrderByCountry] @Country_region = ‘US’ No entanto, quando mudamos o filtro para ‘US”, é possível visualizar um comportamento do plano execução um pouco diferente. Como nosso objetivo neste post não é efetuar uma análise de performance e sim demonstrar a funcionalidade do plan guide, vamos partir do princípio que através de uma análise recorrente e muitos testes realizados, ficou claramente identificado (ficticiamente) que o segundo plano se aplica melhor a todos os filtros desta procedure, no entanto, esta aplicação é de terceiros e não temos qualquer possibilidade de solicitar para que seja colocado a hint diretamente no código. Neste ponto que mais uma vez entramos com o plan guide, iremos mostrar a seguir uma forma de se alterar o comportamento da execução de query através da criação de um guia de plano. EXEC sp_create_plan_guide @name = N’Guide1′, @stmt = N’SELECT * FROM Sales.SalesOrderHeader AS h INNER JOIN Sales.Customer AS c ON h.CustomerID = c.CustomerID INNER JOIN Sales.SalesTerritory AS t ON c.TerritoryID = t.TerritoryID WHERE t.CountryRegionCode = @Country_region’, @type = N’OBJECT’, @module_or_batch = N’Sales.GetSalesOrderByCountry’, @params = NULL, @hints = N’OPTION (OPTIMIZE FOR (@Country_region = N”US”))’; Criamos o plan guide referente a procedure que estávamos executando e podemos perceber que desta vez “setamos” o parâmetro @module_or_batch com o nome do objeto. Neste caso estamos passando um hint para que todos os parâmetros utilizem o plano de execução igual ao do filtro ‘US’. Ficou meio confuso certo? Explicarei melhor! O hint “optimize for” tem como objetivo passar ao Query Optimizer a “dica” para que ele use o mesmo plano para todas variações de filtro, utilizando como base o filtro neste caso de @country_region =’US’. Sendo assim, todos os filtros utilizarão o mesmo plano do filtro passado ao plan guide. Desta forma se executarmos novamente as chamadas da procedure teremos os resultados abaixo: DBCC FREEPROCCACHE EXEC [Sales].[GetSalesOrderByCountry] @Country_region = ‘FR’ DBCC FREEPROCCACHE EXEC [Sales].[GetSalesOrderByCountry] @Country_region = ‘US’ Podemos ver acima as duas chamadas da procedure utilizando exatamente o mesmo plano de execução. Neste ponto, acredito que alguns possam estar afirmando: “O query store faz isto e de maneira visual, minha análise é apenas através de um gráfico”. Eu concordaria plenamente, mas o objetivo principal é observar que o plan guide permite que possamos refinar muito mais nossa análise e colocar a nossa regra sem necessidade de mexer com aplicação ou alteração de código. TEMPLATE PLAN GUIDE Este tipo de plan guide só pode ser usado para as hints PARAMETRIZATION FORCE ou PARAMETRIZATION SIMPLE. Como o objetivo não é explicar como funciona a função PARAMETRIZATION aqui, segue os links para entendimento das opções. https://technet.microsoft.com/en-us/library/ms175037(v=sql.105).aspx https://technet.microsoft.com/en-us/library/ms186219(v=sql.105).aspx Para utilizarmos template plan guide, precisamos seguir alguns pré-requisitos, onde será necessário utilizarmos uma outra procedure chamada sp_get_query_template, além de “setarmos” o valor para @params, diferentemente dos outros dois tipos de plan guide, onde não existia necessidade de “setar” está variável e nem utilizar a procedure mencionada. Cenário Após uma análise efetuada, identificamos que determinada query poderia se beneficiar da utilização da opção PARAMETERIZATION = FORCED, no entanto, sabemos que se habilitarmos esta opção a nível de banco de dados, teríamos problemas em outras querys que estão em atividade neste mesmo banco de dados. Neste momento que os templates são úteis para nós DBAs. Através deles, podemos forçar o SQL Server utilizar apenas para uma determinada sentença a utilização da parametrização forçada. Saiba mais aqui. DBCC FREEPROCCACHE; GO SELECT * FROM Sales.SalesOrderHeader AS h INNER JOIN Sales.SalesOrderDetail AS d ON h.SalesOrderID = d.SalesOrderID WHERE h.SalesOrderID = 45639; GO SELECT * FROM Sales.SalesOrderHeader AS h INNER JOIN Sales.SalesOrderDetail AS d ON h.SalesOrderID = d.SalesOrderID WHERE h.SalesOrderID = 45640; Após limpar o cache e executarmos as duas consultas, podemos verificar que nenhuma delas foram parametrizadas, ou seja, estão seguindo o comportamento padrão do SQL Server (SIMPLE). No entanto, sabemos que neste caso esta consulta se beneficiaria muito se a mesma fosse executada de maneira parametrizada, porém, mais uma vez apenas para fins de aprendizado, “não temos qualquer possibilidade de alterar esta query” (afim que passe a ser parametrizada). A única forma seria forçando um comportamento do SQL Server, onde sabemos que não podemos mudar a nível de banco de dados, pois seria benéfico para este processo, porém atrapalharia muitos outros processos que estão em produção neste momento. Para resolver este problema podemos criar um template, que irá utilizar a parametrização forçada apenas para a query passada na procedure. Vamos ver como isto funciona: DECLARE @sample_statement nvarchar(max); DECLARE @paramlist nvarchar(max); EXEC sp_get_query_template N’SELECT * FROM Sales.SalesOrderHeader AS h INNER JOIN Sales.SalesOrderDetail AS d ON h.SalesOrderID = d.SalesOrderID WHERE h.SalesOrderID = 45639;’, @sample_statement OUTPUT, @paramlist OUTPUT EXEC sp_create_plan_guide @name = N’Template_Plan’, @stmt = @sample_statement, @type = N’TEMPLATE’, @module_or_batch = NULL, @params = @paramlist, @hints = N’OPTION(PARAMETERIZATION FORCED)’; Podemos notar que antes de criar o plan guide desta vez, passamos a query como parâmetro da procedure sp_get_query_template e nomeamos uma saída denominada @paramlist. Este citado é passado como parâmetro de entrada na criação do Plan guide, “setamos” o @type desta vez como Template, o @stmt também recebe a saída da sp_get_query_template e logicamente a hint é informada dentro do plan guide. Vamos verificar como fica a cache após executarmos os passos acima. DBCC FREEPROCCACHE; GO SELECT * FROM Sales.SalesOrderHeader AS h INNER JOIN Sales.SalesOrderDetail AS d ON h.SalesOrderID = d.SalesOrderID WHERE h.SalesOrderID = 45639; GO SELECT * FROM Sales.SalesOrderHeader AS h INNER JOIN Sales.SalesOrderDetail AS d ON h.SalesOrderID = d.SalesOrderID WHERE h.SalesOrderID = 45640; Percebemos que agora foi criado um objeto do tipo prepared o qual parametrizou a consulta que passamos como template. Abaixo segue a query na integra: (@0 int)select * from Sales . SalesOrderHeader as h inner join Sales . SalesOrderDetail as d on h . SalesOrderID = d . SalesOrderID where h . SalesOrderID = @0 Com isso concluímos toda parte de implementação de plan guide. Gerenciamento de Plan guide Podemos gerenciar nossos guias de planos, para isto utilizamos a procedure chamada sp_control_plan_guide. Temos seis valores obrigatórios possíveis para executarmos este procedimento, são eles: DISABLE, DISABLE ALL, ENABLE, ENABLE ALL, DROP e DROP ALL. Podemos colocar o nome do plan guide, no entanto este é opcional. Exemplo: Sp_control_plan_guide DISABLE,’Template_Plan’ Considerações sobre Plan guide O SQL Server evoluiu muito e nas versões mais recentes possui features como o query store que estão chegando para auxiliar nós DBAs no troubleshooting de querys do nosso dia-dia. No entanto, acredito que o Plan guide ainda possui sua função, apesar de necessitar de muita análise e refinamento, acredito que pode ser muito útil em casos onde sabemos que a utilização de determinadas hints são benéficas ao ambiente. Todos os cenários foram criados, forçando um ambiente para se gerar a necessidade da utilização do Plan-guide, no entanto, todos foram cenários fictícios, em momento algum o objetivo foi criar ambientes focados em analises verdadeiras ou onde a leitura de páginas e IO fizessem a diferença. Reitero que todo cenário foi criado apenas para demonstrar a funcionalidade do Plan guide. Muito obrigado a todos, quaisquer dúvidas fiquem à vontade para entrar em contato. caio.amante@dataside.com.br https://www.facebook.com/caio.amante Referencia: Microsoft SQL Server Internals 2012 – Kalen Delaney
- Igor Santos, consultor Dataside, participa de Meetup na Microsoft
No dia de hoje, 06/06, o Microsoft MVP e Data Platform Consultant da Dataside, Igor Santos, participou de um evento da Microsoft no Rio de Janeiro, o Microsoft Meetup reúne profissionais para compartilhar conhecimentos e interesses entre si! Ele foi convidado a palestrar e compartilhar suas experiências sobre inovações na área de banco de dados. Confira mais em nosso álbum de fotos!
- Dataside participa do SQLSaturday em Belo Horizonte
No último final de semana, a Dataside marcou presença no SQLSaturday, na edição de Belo Horizonte. O evento contou com palestras e foi voltado para profissionais e estudantes de SQL Server e Microsoft Data Platform em geral. As palestras foram ministradas por profissionais de vários locais do país. Caio Amante e Jéssica Lima da equipe da Datasite também palestraram! Confira algumas fotos!
- Utilizando Dense_Rank() para classificar minhas séries. (Off Topic)
Boa noite galera, um pouco sem sono nessa madrugada resolvi listar minhas séries favoritas. Bom provavelmente eu posso ter esquecido de listar algumas, essa lista abaixo são apenas de séries que eu já assisti, estou assistindo ou esta na minha lista para assistir, como pode ver na lista tem apenas 2 animes, porém tem muito mais que eu gostaria de listar, mas vou ficar por aqui rs. Abaixo um script para gerar as informações: USE MASTER GO IF(SELECT DB_ID(‘DB_SERIES’)) IS NOT NULL BEGIN ALTER DATABASE DB_SERIES SET SINGLE_USER WITH ROLLBACK IMMEDIATE DROP DATABASE DB_SERIES END GO CREATE DATABASE DB_SERIES GO USE DB_SERIES GO CREATE TABLE MinhasSeries (Id int identity(1,1) Primary key, Nome varchar(200),Assistindo_Assistido bit, NaLista bit, Peso tinyint) GO INSERT INTO MinhasSeries Values (‘Game of Thrones’,1,0,5), (‘Breaking Bad’,1,0,5), (‘The Walking Dead’,1,0,4), (‘Prison Break’,1,0,5), (‘Vikings’,1,0,4), (‘The Flash’,1,0,3), (‘How I Met Your Mother’,1,0,5), (‘House’,1,0,2), (‘Sons of Anarchy’,1,0,2), (‘Os Simpsons’,1,0,4), (‘Arrow’,1,0,3), (‘Mr. Robot’,1,0,4), (‘Narcos’,1,0,4), (‘Death Note’,1,0,5), (‘The Big Bang Theory’,1,0,4), (‘Gotham’,0,1,1), (‘The 100’,1,0,3), (‘Todo Mundo Odeia o Chris’,1,0,4), (‘Black Mirror’,0,1,1), (‘Dexter’,0,1,1), (‘Eu, a Patroa e as Crianças’,1,0,4), (‘Um Maluco no Pedaço’,1,0,4), (‘Spartacus’,1,0,4), (‘Marvels Agents of S.H.I.E.L.D.’,0,1,1), (‘Chuck’,1,0,3), (‘Lie To Me’,0,1,1), (‘Better Call Saul’,1,0,3), (‘The Mentalist’,0,1,1), (‘Modern Family’,1,0,2), (‘Chaves’,1,0,4), (‘Smallville’,1,0,2), (‘Fear The Walking Dead’,1,0,2), (’24 Horas’,0,1,1), (‘Two And a Half Men’,1,0,5), (‘The O.C.’,1,0,2), (‘Lost’,0,1,1), (‘Under The Dome’,1,0,3), (‘Supergirl’,0,1,1), (‘Luke Cage’,1,0,3), (‘The Last Kingdom’,0,1,1), (‘Vai Que Cola’,1,0,2), (‘Falling Skies’,1,0,2), (‘Roma’,1,0,4), (‘Uma Família da Pesada’,1,0,3), (‘The Last Man on Earth’,0,1,1), (‘Xena: A Princesa Guerreira’,1,0,2), (‘3%’,1,0,2), (‘Chapolin’,1,0,4), (‘BoJack Horseman’,0,1,1), (‘Os Dez Mandamentos’,0,1,1), (‘O Atirador’,0,1,1), (‘Futurama’,1,0,3), (‘South Park’,1,0,4), (‘Heroes’,1,0,4), (‘Kyle XY’,1,0,3), (‘Jericho’,1,0,3), (‘Dragon Ball Z’,1,0,4), (‘Californication’,0,1,1), (‘Anger Management’,1,0,2), (‘Cosmos’,0,1,1), (‘Through the Wormhole’,1,0,3), (‘Stranger Things’,0,1,1), (‘HomeLand’,0,1,1), (‘BlackList’,0,1,1), (‘House of Cards’,1,0,2), (‘Sherlock’,0,1,1), (‘Friends’,1,0,2), (‘Demolidor’,0,1,1) SELECT NOME,DENSE_RANK() OVER (ORDER BY PESO DESC) POSICAO FROM MinhasSeries ORDER BY POSICAO,NOME A lista não esta ordenada e nem classificada por gênero fui adicionando conforme vinha em minha cabeça. Utilizei uma classificação de 1 a 5, onde 5 é o mais TOP, porém não quer dizer que 1 ou 2 são necessariamente ruins, pode ser que eu esteja começando a assistir por isso ela tenha uma classificação baixa. Utilizei a função DENSE_RANK() para classificar e trazer na ordem mostrada abaixo, caso eu utiliza-se a função RANK() as séries que estão na segunda posição iriam aparecer como posição 7, pois o RANK pula esse intervalo. https://msdn.microsoft.com/en-us/library/ms173825.aspx Esse seria o resultado com o RANK(), da pra ver que ele pula do 1 para o 7, vamos ver o resultado com DENSE_RANK(). Acredito que o resultado não tenha nada de surpresa né?! É claro que isso sempre gera uma pequena discussão saudável rs, porém é aquela questão do velho ‘Gosto não se discute’ rs. Ainda tenho uma lista grande pela frente para assistir (21 séries). Bom caso eu tenha esquecido de alguma série legal, ou se tem recomendações de boas séries, deixe no comentário. Valeu galera, esse foi um post rápido para descontrair, ainda vimos um pouco de TSQL haha, até a próxima. Reginaldo Silva
- Rebuild não zera a fragmentação?
Fala galera, hoje vou falar de um caso muito legal, muita gente já passou por isso e as vezes não soube o porque de acontecer esse fenômeno, em algum momento você deve ter encontrado índices bem fragmentados em seu ambiente, fragmentações como 99% fragmentado e após ao rodar a rotina de Rebuild ele ficou com 70% ainda, um numero alto para fragmentação de índice, e você rodou novamente o rebuild desse índice e ele foi para 80%, rodou novamente ele foi para 65%, um tanto quanto estranho não acha ? Bom a resposta pra isso provavelmente vai ser que esse índice é bem pequeno, mas pequeno quanto? Para isso precisamos entender um pouco das estruturas internas do SQL Server, conhecer um pouco sobre Extents, páginas de controle GAM, SGAM, IAM e PFS. Quando criamos uma tabela ou índice eles são armazenados em páginas de 8Kb, extent é uma unidade composta por 8 páginas de 8Kb logo 64Kb, no SQL Server podemos ter 2 tipos de extent sendo elas extent uniforme e mista. Extents mista são composta por 8 páginas porém logicamente sem nenhuma ligação, elas podem ser compartilhadas por até 8 objetos diferentes até o objeto crescer e poder se alocar em uma estrutura de extents uniforme. Extents uniforme é o conjunto de 8 páginas de 8Kb dedicado a um único objeto apenas. Podemos ver então que para objetos pequenos compensa bastante o modelo de Extent mista, por exemplo uma tabela de configurações que tem poucas linhas pode estar armazenado em uma extent mista ocupando apenas 1 pagina de 8Kb, caso não existisse esse modelo ela estaria ocupando uma extent inteira 8 páginas 64 Kb sem ter necessidade. Entendemos aqui um pouco sobre extents, precisamos saber que as extents mistas são mapeadas pela página de controle chamada SGAM(Shared Global Allocation Map) e as extents uniforme são mapeadas pelas páginas de controle GAM(Global Allocation Map). Tudo isso é mapeado pela página de controle chamada IAM(Index Allocation Map), ambas páginas de controle IAM, GAM e SGAM podem rastrear até 4 GB de páginas. Bom não detalhei tanto sobre essas páginas e estruturas pois vou deixar uns links de referencia para leitura do post não ficar tão extenso e virar uma leitura massacrante. Bom vamos ao que interessa, como tudo isso influência no rebuild do índice ? Vamos montar uma demo. USE MASTER GO IF(SELECT DB_ID(‘TESTEINDICE’)) IS NOT NULL BEGIN ALTER DATABASE TESTEINDICE SET SINGLE_USER WITH ROLLBACK IMMEDIATE DROP DATABASE TESTEINDICE END GO CREATE DATABASE TESTEINDICE GO USE TESTEINDICE GO CREATE TABLE TBINDEX1 (CAMPO1 INT DEFAULT RAND() * 10000000, CAMPO2 INT DEFAULT RAND() * 10000000, CAMPO3 CHAR(50) DEFAULT(‘AA’)) GO CREATE INDEX IDX_TBINDEX1 ON TBINDEX1(CAMPO1) GO INSERT INTO TBINDEX1 DEFAULT VALUES GO 5000 Acima script para simular nosso ambiente de teste, podemos ver que estamos inserindo 5000 registros aleatórios para gerar um pouco de fragmentação no índice. Vamos utilizar a SP_SHOWINDEX para ajudar na análise. Podemos ver uma fragmentação de 93,75% sobre 16 páginas, vamos cavar um pouco mais fundo então. SELECT O.NAME AS TABLE_NAME,P.INDEX_ID, I.NAME AS INDEX_NAME , AU.TYPE_DESC AS ALLOCATION_TYPE, AU.DATA_PAGES, PARTITION_NUMBER FROM SYS.ALLOCATION_UNITS AS AU JOIN SYS.PARTITIONS AS P ON AU.CONTAINER_ID = P.PARTITION_ID JOIN SYS.OBJECTS AS O ON P.OBJECT_ID = O.OBJECT_ID JOIN SYS.INDEXES AS I ON P.INDEX_ID = I.INDEX_ID AND I.OBJECT_ID = P.OBJECT_ID WHERE O.NAME = N’TESTEINDICE’ OR O.NAME = N’TBINDEX1′ ORDER BY O.NAME, P.INDEX_ID; GO DBCC IND (‘TESTEINDICE’, ‘TBINDEX1’ , 1); DBCC IND (‘TESTEINDICE’, ‘TBINDEX1’ , 2); — TRACE PARA MOSTRA O DBCC NA GRID DO SQL SERVER DBCC TRACEON (3604); DBCC PAGE (TESTEINDICE, 1, 90, 3); Com o primeiro SELECT podemos ver as seguintes informações: Nossa tabela (HEAP) possuí 44 páginas de dados e nosso índice não cluster possuí 16 páginas de dados. Um pouco mais afundo com DBCC. DBCC IND (‘TESTEINDICE’, ‘TBINDEX1’ , 2); Com ajuda do DBCC IND podemos identificar qual é a página IAM que controla esse índice, vamos mais afundo então. DBCC TRACEON (3604); DBCC PAGE (TESTEINDICE, 1, 89, 3); Com a ajuda do DBCC PAGE podemos investigar mais afundo e descobrir que nosso índice alocou as primeiras 8 páginas como mistas logo quando não cabia mais ele alocou 2 extents uniforme, como já sabemos extents mista são um conjunto de 8 paginas que podem conter até 8 objetos (tabela, índice) , sendo assim a desfragmentação desse cara é realmente desnecessária, pois são poucas páginas e podendo conter objetos diferentes. Vamos rodar um Rebuild nesse índice. ALTER INDEX IDX_TBINDEX1 ON dbo.TBINDEX1 REBUILD Com a ajuda da nossa amiga SP_SHOWINDEX podemos ver novamente a fragmentação do índice, pra garantir rodei 3 vezes o Rebuild mesmo assim continua 50% fragmentado. No print anterior vimos que o índice ainda possuí 12 páginas, olhando novamente ná página IAM conseguimos ver que ele ainda esta alocando páginas em uma extent mista, e apenas 1 extent uniforme agora, bom isso desmistifica o porque da fragmentação do índice ainda estar alta, enquanto tivermos uma alocação em extent mista sempre existira um pouco de fragmentação, essa fragmentação quero explicar no próximo post, mas ela é analisada com base nos níveis folha do índice, ela olha para as páginas onde a próxima página não é a sequência (exemplo, página 50 a próxima pagina deveria ser a 51, se a próxima página for a 75 sabemos que o índice não está 100% desfragmentado). Vamos inserir um pouco mais de registros. Com o índice bem fragmentado e agora com 51 páginas vamos dar um outro Rebuild nele. ALTER INDEX IDX_TBINDEX1 ON dbo.TBINDEX1 REBUILD Podemos ver nossa fragmentação em 0%, mas porque só depois de inserir 10000 registros dar um Rebuild ? Podemos ver que a quantidade de página do nosso índice após o Rebuild esta com 34 páginas, bom será que ainda vale a pena utilizar uma extent mista com 34 páginas ? Aparentemente para o SQL Server não vale a pena, podemos ver que agora nosso índice não esta mais alocando uma extent mista e esta diretamente alocando 2 extent uniforme. Com isso podemos ver que as extents mistas impedem de termos um índice 0% fragmentado, isso não significa que isso é uma coisa ruim, simplesmente seu índice é pequeno e uma alocação em extent mista não irá afetar sua performance assim como uma fragmentação de 90% afetará tão pouco nesse caso, bom gente como sempre dizemos tudo depende nessa nossa área, é claro que cada caso é um caso e precisa ser analisado bem, nesse caso não existe uma recomendação especifica mas eu começaria a me preocupar com índices com pouco mais de 100 páginas que ainda sim parece ser um número pequeno, mas como disse ‘EU’, não é uma via de Regra, cada caso é um caso. Dica: No SQL Server 2016 o TraceFlag 1118 já vem ativo por default, então esse tipo de ocasião não acontece, caso queira simular no SQL Server 2016 precisa alterar uma propriedade no banco de dados. ALTER DATABASE TESTEINDICE SET MIXED_PAGE_ALLOCATION ON Esse comando seria equivalente a desabilitar o traceflag 1118 em outras versões posteriores. Pessoal sei que é um assunto um tanto quanto complexo, espero ter explicado em detalhes, mas se ficou dúvida sobre qualquer estrutura deixe seu comentário, me envie um e-mail, pode me chamar sem problemas, as vezes escrevemos coias que são claras pra nós, porém escrevendo é bem difícil de explicar detalhadamente, em posts futuros quero gravar alguns videos. Bom muito obrigado pela sua atenção e até a próxima. Referencias : Inside the Storage Engine: Anatomy of an extent http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-an-extent/ Misconceptions around TF 1118 http://www.sqlskills.com/blogs/paul/misconceptions-around-tf-1118/ Inside the Storage Engine >> Inside the Storage Engine: IAM pages, IAM chains, and allocation units http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-iam-pages-iam-chains-and-allocation-units/ SQL Server 2016: The Death of the Trace Flag https://www.brentozar.com/archive/2016/03/sql-server-2016-death-trace-flag/ Reginaldo Silva
- SP_SHOWINDEX V2
Boa noite galera, essas últimas semanas vim trabalhando na procedure SP_SHOWINDEX revendo alguns códigos, implementando algumas dicas que foram passada pelo pessoal, melhorando performance e corrigindo alguns gaps, se você ainda não conhece a SP_SHOWINDEX dê uma olhada no link abaixo: https://blogdojamal.wordpress.com/2016/11/28/sp_showindex/ Abaixo um pouco das mudanças, acredito que esta procedure esteja ficando muito boa, esta me ajudando muito nos últimos tempos, sou suspeito de falar então baixa, utiliza e deixa sua opinião ou alguma dica para estarmos sempre melhorando ela. @IS_DUPLICATE é um parâmetro novo adicionado na versão 2.0 onde quando especificado o valor 1 para esse parâmetro é feito uma varredura em todos os índices afim de encontrar duplicidades, o result set é ordenado pelo nome do índice e suas duplicidades. O que é levado em consideração para retornar o índice duplicado é apenas os campos que compõe o índice e sua ordem na chave, não é levado em consideração o INCLUDE do índice para essa validação. Nessa atualização foi implementado a busca pelo LIKE, onde você não precisa saber o nome completo da tabela e pode utilizar expressões regulares para filtrar a tabela que deseja dentro do %%. Expressões regulares no SQL Server https://msdn.microsoft.com/pt-br/library/ms174214.aspx Na versão 2.0 foi introduzido também o parâmetro @INDEX_NAME onde você pode fazer filtro pelo nome do índice ou parte dele utilizando expressões regulares assim como já citado acima. Outra novidade foi uma dica deixada nos comentários do post da SP_SHOWINDEX pelo Renato Siqueira. Foi implementado dentro do parâmetro @INDEX_DETAILS para retornar informações sobre particionamento, como podemos ver acima no print, é retornado o ‘partition_scheme’, ‘file_groupname’, ‘funciton_name’ e ‘partitions’ do índice. Exemplos combinando diversos parâmetros. Vemos que os parâmetros podem ser flexíveis e temos informações ricas sobre os índices de forma mais fácil e pratica, espero que essa procedure possa ajudar a muitos em seu dia-a-dia. Algumas coisas estão sendo estudadas para implementar na próxima release, entre elas quero adicionar ‘Indices In-Memory’ e ‘Column Store índices’, estou pensando também em compilar uma versão da SP_SHOWINDEX para SQL Database, aos poucos vamos chegando no objetivo. Bom galera é isso faça o download da versão 2.0 da SP_SHOWINDEX e avalie a sua usabilidade, não esqueça de deixar sua opinião ou dica, é muito importante para conseguirmos evoluir cada vez mais, até a próxima! Link para download: Atualizado em 06/01/2017 18:30 – Corrigido problema com o parâmetro @IS_DUPLICATE. https://drive.google.com/open?id=0B5j2xWOxw677aEs3U2R6UDN2Z1U Reginaldo Silva
- SP_Columns
Boa tarde pessoal. Vi uma pergunta em um grupo de SQL Server e lembrei dessa dica. A pergunta era: Como encontrar as tabelas que possuem uma determinada coluna? A resposta parece simples, e de fato ela é, a maioria vai pela query tradicional: –Query para listar todas as tabelas que possuem a coluna chamada ‘APELIDO’ SELECT * FROM SYSOBJECTS O INNER JOIN SYSCOLUMNS C ON O.id = C.id WHERE O.xtype = ‘U’ AND C.name = ‘APELIDO’ A junção da ‘sysobjects’ com a ‘syscolumns’ onde ‘xtype = ‘U” filtra apenas tabelas de usuários, um consulta bem simples de se fazer. Porém conseguimos atingir o mesmo resultado também com uma procedure nativa do SQL Server chamada ‘SP_COLUMNS’ conforme exemplo abaixo: — Filtra todas as tabelas que possuem a coluna ‘Apelido’ SP_COLUMNS @table_name = ‘%%’,@column_name = ‘APELIDO’ Podemos ver que os Result sets são diferentes, no primeiro traz algumas informações sobre o objeto (tabela) e sobre a coluna, no segundo as informações são apenas sobre a coluna como o datatype, precisão, tamanho, posição, se permite null… Porém se o que te interessa é saber apenas quais tabelas possuem aquela coluna já atende sua necessidade. Podemos também filtrar a coluna como se fosse um LIKE ‘%%’, por exemplo quero todas as tabelas que possuem alguma coluna que comece com ‘ID_’. Nesse caso especifiquei o ‘@table_owner’ para não trazer informações sobre os metadados de sistema. Se você prestou atenção deve estar se perguntando porque da coluna ‘IDPLAN’ esta sendo exibida ?! A resposta para isso: Expressões regulares, esse carácter(_) representa ‘qualquer coisa’ ou ‘qualquer carácter ‘. https://msdn.microsoft.com/pt-br/library/ms174214.aspx O correto então seria assim: SP_COLUMNS @table_name = ‘%%’,@table_owner = ‘dbo’,@column_name = ‘ID[_]%’ Bom podemos também fazer o contrário, podemos pelo nome da tabela saber quais colunas pertencem a ela. SP_COLUMNS @table_name = ‘TB_MESAS’,@table_owner = ‘dbo’ Conseguimos ver facilmente as colunas dessa tabela e temos praticamente toda as informações sobre essas colunas. Posso pegar todas as tabelas que começam com um nome especifico e todas as suas colunas, esse result set é bem rico em informações sobre as colunas. Bom galera era essa a dica, utilizo muito no dia-a-dia essa procedure é bem fácil e rápido de pesquisar com ela, o SQL Server tem varias outras procedures como essa, vou tentar falar mais sobre elas em outros posts, até a próxima. Quem quiser saber mais detalhes sobre a SP_COLUMNS abaixo o link do BOL. https://msdn.microsoft.com/en-us/library/ms176077.aspx Reginaldo Silva
- Feliz Natal (Geometry)
Boa tarde pessoal, ano de 2016 está acabando e venho aqui desejar a todos um Feliz Natal e um próspero ano novo, que o ano de 2017 seja melhor que 2016. Esse ano de 2016 pra mim foi de muitas mudanças, consegui evoluir muito profissionalmente, fiz diversos cursos muito bons, criei meu blog que já estava no papel há muito tempo, troquei de emprego que com certeza foi ótimo pra mim, mudei de cidade entre outras coisas boas que me aconteceram, assim como coisas boas algumas ruins também aconteceram, aliás a vida não é só de alegrias né, mas como um todo estou fechando o ano muito bem. Deixo para vocês abaixo o meu Feliz Natal de uma maneira diferente: SELECT CAST (‘POLYGON((1 10, 1 11, 2 11, 2 10.8, 1.25 10.8, 1.25 10.6, 1.75 10.6, 1.75 10.4, 1.25 10.4, 1.25 10, 1 10))’ as geometry) UNION ALL –F SELECT CAST (‘POLYGON((2 10, 2 11, 3 11, 3 10.8, 2.25 10.8, 2.25 10.6, 2.75 10.6, 2.75 10.4, 2.25 10.4, 2.25 10.2, 3 10.2, 3 10, 2 10))’ as geometry) UNION ALL –E SELECT CAST (‘POLYGON((3.15 11, 3.15 10, 3.85 10, 3.85 10.2, 3.35 10.2, 3.35 11, 3.15 11))’ as geometry) UNION ALL –L SELECT CAST (‘POLYGON((4.2 11, 4.8 11, 4.8 10.8, 4.6 10.8, 4.6 10.2, 4.8 10.2, 4.8 10, 4.2 10, 4.2 10.2, 4.4 10.2, 4.4 10.8, 4.2 10.8, 4.2 11))’ as geometry) UNION ALL –I SELECT CAST (‘POLYGON((5 11, 6 11, 5.4 10.2, 6 10.2, 6 10, 5 10, 5.6 10.8, 5 10.8, 5 11))’ as geometry) UNION ALL –Z SELECT CAST (‘POLYGON((1 10, 1 9, 1.2 9, 1.2 9.8, 1.8 9, 2 9, 2 10, 1.8 10, 1.8 9.3, 1.3 10, 1 10))’ as geometry) UNION ALL –N SELECT CAST (‘POLYGON((2 9, 2 10, 3 10, 3 9, 2.75 9, 2.75 9.3, 2.25 9.3, 2.25 9, 2 9),(2.25 9.5, 2.25 9.8, 2.75 9.8, 2.75 9.5, 2.25 9.5))’ as geometry) UNION ALL –A SELECT CAST (‘POLYGON((3 9.8, 3 10,4 10, 4 9.8, 3.6 9.8, 3.6 9, 3.4 9, 3.4 9.8, 3 9.8))’ as geometry) UNION ALL –T SELECT CAST (‘POLYGON((4 9, 4 10, 5 10, 5 9, 4.75 9, 4.75 9.3, 4.25 9.3, 4.25 9, 4 9),(4.25 9.5, 4.25 9.8, 4.75 9.8, 4.75 9.5, 4.25 9.5))’ as geometry) UNION ALL –A SELECT CAST (‘POLYGON((5.15 10, 5.15 9, 5.85 9, 5.85 9.2, 5.35 9.2, 5.35 10, 5.15 10))’ as geometry) –L Como sabemos o SQL Server suporta alguns tipos de dados espaciais, sendo um deles o tipo de dados ‘Geometry’, com ele podemos brincar com algumas coordenadas e daí pra frente a imaginação é o limite. Os tipos de dados espaciais foram incluído na versão do SQL Server 2008. O resultado so SELECT acima é esse: Hum, nada demais não? como você pode ver ao lado da aba ‘Results’ apareceu uma nova aba chamada ‘Spatial Results’ ali é onde a mágica acontece. E temos essa bela imagem dentro do nosso SSMS, daqui pra frente sua imaginação pode fazer toda a diferença, já vi alguns feras postando imagens sensacionais brincando com esse tipo de dados do SQL Server. Se interessou ? Da uma lida sobre os tipos de dados espacias no link abaixo: https://msdn.microsoft.com/en-us/library/cc280487.aspx Um Feliz natal a todos vocês. Reginaldo Silva
- SP_SHOWINDEX
Fala galera, hoje venho com uma novidade pra vocês, um script pra ajudar muito no seu dia-dia. Quer saber como estão seus indices, se estão sendo de fato utilizados, como esta a fragmentação, quer ver as colunas do INCLUDE então acho que vai gostar desse script. Sabemos das limitações da SP_HELP que não mostra os campos do INCLUDE, da SP_HELPINDEX que nos dá poucas informações, das dificuldades de ter que ficar desenvolvendo scripts para ver utilização de indices, tamanho, fragmentação, colunas no include e etc. Com intuito de facilitar nossa vida caso você não tenha nada parecido eu e meu amigo Paulo Katayama estamos disponibilizando uma procedure chamada SP_SHOWINDEX que vai te ajudar muito, mostraremos um pouco dela logo abaixo. Deixa eu falar um pouco como surgiu essa procedure, esse script que traz essas belas informações foi desenvolvido pelo meu amigo Paulo Katayama vulgo Japa rs o qual tive a grande oportunidade de trabalhar ao lado dele e aprender muito com esse fera, sempre utilizei esse script nos ambientes que administro, porém ultimamente percebi que poucas pessoas conseguiam chegar com facilidade nessas informações exibidas por esse script, daí surgiu então a ideia de compartilhar com vocês esse script de uma forma simples de utiliza-lo através de uma Store Procedure, espero que gostem. Compartilho com vocês essa Store Procedure com total consentimento do meu amigo Paulo Katayama. Como será a primeira versão da procedure contamos com a ajuda de vocês para validarem suas funcionalidades, qualquer dúvida, sugestão ou problemas que venha a ter com ela entre em contato conosco para que possamos melhora-la cada vez mais. Lembre-se utilize por sua conta e risco, não nos responsabilizamos pelo seu uso ‘rs’. Vamos lá, vamos conhecer então a SP_SHOWINDEX. Cabeçalho da procedure, informações do autor e pagina para contato. Parâmetros suportados na chamada da procedure. Descrição de cada coluna exibida. Essas informações acima você consegue acessar na procedure chamando com o parâmetro @HELP = 1. Vamos ver algumas demonstrações. A chamada da SP_SHOWINDEX acima filtrando apenas a tabela ‘OrdersBig’, essa chamada retorna apenas um ResultSet, eu dividi em 3 partes no print para ficar melhor a visualização. Podemos ver então algumas coisas legais já como quantidade de seeks, scans, lookups, updates, colunas que compõe o índice, colunas que estão no include do índice, comando para excluir o índice, comando para criar o índice, ultima vez que foi executado um seek, scan, lookup e update, se o índice é uma PK, se o índice é único e se o índice esta habilitado ou não. @INDEX_DETAILS -Podemos ver quantidade de paginas do índice, quantidade de linhas aproximada, fator de preenchimento do índice e tipo de compressão.(Atualizado 29/11/2016) @INDEX_FRAGMENTATION – Podemos ver a média de fragmentação de cada índice e a quantidade de paginas. @NOTUTILIZED – Podemos ver os indices que nunca foram utilizados, ou que foram utilizados a mais de 1 mês. @LIMITED – Uma visualização mais simples apenas com as principais colunas. @IS_DISABLED – Mostra indices desabilitados. Podemos também combinar qualquer parâmetro na chamada da procedure. Podemos chamar sem nenhum filtro, irá trazer informações de todos os indices de tabelas de usuários. @HELP – Informações sobre a procedure. Bom galera é isso, baixem ai a primeira versão e deixe seu feedback para podermos melhora-lá, espero que gostem. Dicas, sugestões, criticas são sempre bem vindas galera, alguns parâmetros estão ainda sendo avaliados e podemos mudar em breve, então se tiverem sugestões deixe ai no comentário, até a próxima. Link para Download: https://drive.google.com/file/d/0B5j2xWOxw677aEs3U2R6UDN2Z1U/view?usp=sharing Aplicado correções e alguns novos itens. Atualizado em: 06/01/2017 Reginaldo Silva












