Arquivos de tags: servidor

Como minha query chega ao servidor?…

Todos sabemos que o SQL Server aceita varios protocolos de conexão, como Shared Memory, VIA e TCP/IP por exemplo, porem, a partir do momento em que uma conexão é feita com uma base SQL Server, toda sua comunicação sera feita atravez de pacotes TDE (Tabela Data Stream), ou seja, quando enviamos um select de nosso Client (Maquina local por exemplo…) para o servidor, na rede, estamos enviando-o via protocolo TDS.

No SQL Server, existe um protocolo TDS para cada meio de conexão alem de uma especifica para a conexão DAC.

Existem algumas versões que foram desenvolvidas com o passar do tempo deste protocolo, abaixo uma tabela com os diferentes tipos e algumas explicações (Não de minha autoria….).

Anúncios

Grupos no SSRS (SQL Server Reporting Services)

Uma duvida que vejo bastante em foruns e nos emails com duvidas que recebo sobre SSRS (SQL Server Reporting
Services) é em relação a agrupamento, ok, porem, o que é agrupamento…?

Sabe quando uma linha se repete varias vezes, sendo o topo maximo de uma hierarquia, e as diferencas da linha estão em niveis mais baixo, como por exemplo: Estado e cidade, teriamos algo assim…

SP São Paulo
SP Campinas
SP …
RJ …
RJ …

Ou seja, podemos observar que o estado esta aparecendo varias vezes!, o que obviamente fica bem feio, e ruim de ser lido em um relatorio, portanto, a tecnica de agrupamento não só é extremamente pratica e simples de ser aplicada, como em muito casos, simbolo de boa pratica e higienização visual em seu relatorio.

Como curiosidade, ao criarmos um grupo, estamos falando de hierarquia, a mesma que pode ser feita no SSAS (Que sera assunto de posts futuros…).

Abaixo, segue uma breve explicação de como se criar estes grupos (Hierarquias no SQL Server Reporting Services).

OBS: Estou utilizando BIDS 2008, com SQL Server 2008, e uma base chamada AdventureWorksLT, é basicamente a base AdventureWorks que ja conhecemos bem, porem em sua versão Lite, sendo mais leve, e com menos tabelas.
A tabela que utilizarei como exemplo, se chama Product, que contem informações dos produtos que são vendidos na famosa loja de bicicletas.

Passo 1: Criar a conexão com a base de dados e um novo relatorio

Neste passo, não tem segredo, se iniciarmos o BIDS no modo de contrutor de relatorio, muito provavelmente ja ira te saltar uma opção Wizard para informar uma conexão e um relatorio, como o foco deste post não é o desenvolvimento inicial de relatorios, irei abstrair este passo, qualquer duvida no mesmo, fique a vontade para me mandar email ou perguntar nos comentarios.

Passo 2: O Objeto

O objeto que utilizaremos para se criar os grupos se chama Tablix, basta arrastar da caixa de ferramenta, um deste objeto para seu relatorio.

Passo 3: Criação de um DataSet com o SELECT no banco de dados

Aqui, basta criar um novo DataSet, utilizando a conexão previamente criada, e escrever seu SELECT, no meu exemplo, estou utilizando:

SELECT ProductCategoryID, Name
FROM SalesLT.Product
WHERE ProductCategoryID IN (9, 10)

O filtro, é apenas para ficar visualmente mais limpo, tendo em vista que o ponto do post não é a analise de dados, e sim o agrupamento dos mesmos.

Feito isso, fica bem simples o agrupamento, abaixo de seu relatorio, deve ter os campos:
– Grupos de linhas
– Grupos de colunas

Como temos os dados no formato exemplificado acima, e queremos deixa-lo…

SP São Paulo
Campinas
RJ …

Iremos utilizar o agrupamento de linhas.

Então, basta voce selecionar o campo mais alto de sua hierarquia, que no nosso caso é o ProductCategoryId, e arrasta-lo para o grupo de linhas, e em seguida, ir descendo o nivel de sua hierarquia, portanto, arrastando tambem, o campo Name, como na imagem abaixo:

Com o intuito de melhor visualização e como não temos nenhum outro dados, estou setando a ultima coluna com visibilidade oculta, aqui, seria interessante colocar por exemplo, o total, um grafico por linha e afins, as possibilidades são infinitas.

Então, teriamos uma visualisação mais ou menos assim:

Cumulative Update #01 para SQL Server 2012

A microsoft ja liberou o Cumulative Update #01 para o SQL Server 2012, muitos “bugzinhos” foram corrigidos.

Segue link para Download: http://support.microsoft.com/kb/2679368/pt-br

SQL Server 2012 – Prova 71-465

Hoje, como alguns ja sabem, fiz a prova 71-465 do SQL Server 2012, referente a desenvolvimento, e em comparação com as do SQL Server 2008, foi possivel notar algumas diferenças:

– Questões mais objetivas
– Novos pradrões de perguntas
– Questões mais focadas na praticidade do dia-a-dia do que no surrealismo do mundo utopico

Em poucas palavras, eu resumiria a prova como um novo formato bem interessante.

Entrando em detalhes….
Quando fiz minha prova prova de certificação (Oracle) estava diante de questões bem simples e diretas, quase um “O que isso significa” ou “Como se resolve isso”, ao realizar a minha primeira certificação Microsoft, sinceramente, assustei! rs…Havia cenarios, ou aquelas questões que todos nós “amamos”, a famosa: CHOOSE ALL THAT APPLY, Enfim, ao meu ver, eram questões maiores, mas não necessariamente mais complexas, neste novo formato que encontrei hoje na prova 71-465, ao meu ver, ela conseguiu ser complexa e objetiva ao mesmo tempo, o novo modo de questão, um famoso “Drag-And-Drop”, achei interessante, mas não exatamente necessario, mas não ficou ruim…. Os casos a serem analisados eram interessantes, vi alguns deles no meu dia-a-dia, a para quem realmente conhece, estava logico a resposta.

Mas, nem tudo são flores, algumas coisas me deixaram muito bravo na prova, a que mais me irritou foi o fato de eu ter de sempre realizar o “scroll completo” de todas as paginas, ainda que o resto da pagina estivesse em branco! Outra coisa que me deixou bravo, foi, depois de toda a revisão, cai, muito provavelmente por erro meu, em uma nova revisão (Não lembrava desta nas outras certificações….) que me deixou irritado, por não conseguir simplismente cancelar, tive de passar uma a uma.

Deixando de lado as frescuras descritas acima, o conteudo da prova em si tambem teve seus momentos ruins, havia questões que ao meu ver eram muito mais interessante em uma prova de Infra do que de SQL Server (Tais tipos de questões antigamente eram inseridas dentro de um contexto maior).

Bom, o resultado, segundo os textos, só saira em “eight weeks”, espero que daqui 2 meses, eu tenha uma boa surpresa!

SQL Server 2012 – Função PARSE

Atualmente, trabalho em uma empresa aonda diariamente lidamos com valores monetarios no formato brasileiro, ou seja, “00,00”, porem, para trabalharmos no SQL Server com Float desta maneira, ele daria erro, a não pelo pelo nivel de linguagem de por default ja é padrão em ingles, então todas as vezes, trabalhamos com o mesmo sendo texto, e fazemos uma troca de “,” para “.”, podendo tratar com o Flat nativamente do SQL Server.

A dica teste post, é bem rapida, porem ao meu ver, extremamente util!…Por que não podemos, em tempo de execução, definir uma linguagem para o valor de entrada e obtermos no formato que quisermos, tipo um decimal….Bem, no SQL Server 2012 isso é possivel sim, graças a uma nova função chamada PARSE, sua execução é bem simples, porem seu ganho, enorme!

Veja exemplos:
Tente executar a seguinte consulta:

SELECT CAST(‘10,50’ AS decimal(9,2)) As Resultado

Voce tera um erro de conversão, pois no lugar da “,” deveria ser um ponto para termos os efetivos “dez e conquenta”, agora, veja como resolver este problema com o uso da função PARSE.

SELECT PARSE(‘10,50’ AS decimal(9,2) USING ‘pt-PT’) As Resultado

Voce podera notar que o retorno gerado é “10.50”, como seria se fizessemos a conversão manual, porem agora, pode trabalhar de forma muito mais simples, e mantendo o codigo muito mais limpo, sem as famosas “Gambiarras”.

Espero que tenham gostado, e assim que possivel, continuarei falando das novas funções do SQL Server 2012!!!!

Heap X Clustered, na pratica….

Galera, hoje, irei falar sobre um assunto muito legal!, algo que gosto muito de verdade, que é a ordenação fisica das pagina de uma tabela, bem, todos sabemos que o SQL Server trabalha com uma estrutura de paginas, contendo cada uma 8KB.

Bem, este tema abre varias raizes para varias explicações, neste, quero falar especificamente, ou melhor, mostrar, as diferenças entre uma tabela HEAP e uma tabela Clusterizada.

Do ponto de vista teorico temos a seguinte explicação:

Uma tabela HEAP é aquela que não contem uma indice cluster, portanto, suas paginas são ordenadas e localizadas a partir de uma tabela especial chamada IAM (Index Allocation Map, ou, como ultimamente tem sido chamada, Allocation Unit [AU]). Ja uma tabela Clusterizada possui um indice Cluster e toda sua estrutura sera feita a partir desta caracterisca, ou seja, sua paginas são ligadas diretamente uma na outra, mantendo uma ordem, segundo os dados especificados no indice Cluster.

Vamos ver na pratica como que funciona?…

Primeiro uma criação de tabela simples, algumas inserções de dados e um select apenas para confirmação de inserção:

--Criação de tabela
CREATE TABLE Teste
(
	Id UNIQUEIDENTIFIER
)

--Inserção de dados
INSERT INTO Teste VALUES (NEWID())
GO 3000

--Select de teste de inserção de dados
SELECT *
FROM Teste

Depois, o comando para verificarmos as paginas desta tabela:

DBCC IND('Master', Teste, -1)

O que é legal de observar:
Temos, pela PageType = 10, nosso IAM (ou AU), e PageType = 1, paginas de dados, alem de podermos ver que os campos NextPagePID e PrevPagePID estão todos zerados, ou seja, não ha uma ordernação das paginas.

Criação de um indice não clusterizado

CREATE INDEX IX_01 ON Teste(Id)

Nova verificação das paginas:

DBCC IND('Master', Teste, -1)

Podemos agora observar que as paginas de dados, ou seja, com PageType = 1 continuam ser ordenação entre si, porem, um novo PageType foi introduzido, o PageType 2, que quer dizer que estamos falando de uma pagina de indice, se observar os campos NextPagePID e PrevPagePID, podemos observar que os mesmo estão preenchidos, mantendo uma ordenação conforme se espera de um indice, ou seja, ainda estamos falando de uma tabela HEAP.

Agora, vamos dropar este indice não clusterizado, e criar um indice cluster nesta tabela.

DROP INDEX IX_01 ON Teste

CREATE CLUSTERED INDEX IX_01 ON Teste(Id)

Reexecução do comando de verificação das paginas:

DBCC IND('Master', Teste, -1)

Agora, podemos observar que voltamos a não ter o PageType = 2, porem, agora nossas paginas de dados estão ordenadas pelo campo Id.

Aonde isso pode me ajudar:
Deixo aqui como “lição arrumada” de um projeto de software que pegamos la na empresa, no caso, temos uma tabela de discagem de utiliza um campo NEWID, ou seja, UNIQUEIDENTIFIER como Primary Key (Assim como o campo ID no titulo), ou seja, todas as vezes de alguma inserção era feita na tabela, um novo UNIQUEIDENTIFIER era criado, como o mesmo não segue uma ordem obrigatoria de crescente ou decrescente, toda nova inserção fazia com que o SQL Server se arrumasse inteiro, realocando todas as paginas de sua tabela, com a simples remoção do indice Primary Key deste campo, fizemos qualquer operação reduzir de 45 segundos em media, para no maximo 3 segundos.

SQL Server 2012 – FileTable

Continuando os posts sobre SQL Server 2012, neste, irei comentar sobre um recurso chamado FileTable, que utiliza o recurso FileStream, ja existente em versões anteriores do SQL Server (Como o 2008….).

Bom, o que é este novo recurso? O mesmo foi introduzido com a função de faciliar o acesso a arquivos atraz de aplicações, de forma que seja automatico o mapeamento do arquivo pelo SQL Server, com apenas a simples ação de se colocar o arquivo em uma pasta.

Vale a pena comentar que aqui estou abstraindo o fato de habilitar o FileStream e sua configuração, aonde uma pasta de rede sera criada, muito provavelmente com o nome da propria instancia, no meu caso \\FABRIZZIO-PC\FABRIZZIO12ENT.

Todo o processo consiste em pequenos e simples passos, que são exemplificados a seguir:

– Criação de uma base de dados com um FileGroup com FileStream habilitado

--CRIAR BASE COM FILEGROUP DE FILESTREAM
CREATE DATABASE BlogFileTable
ON
PRIMARY ( NAME = Arch1,
    FILENAME = 'd:\SQL_Server\2012\Data\BlogFileTable.mdf'),
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM( NAME = Arch3,
    FILENAME = 'd:\SQL_Server\2012\Data\filestream')
LOG ON  ( NAME = Archlog1,
    FILENAME = 'd:\SQL_Server\2012\Log\BlogFileTable.ldf')
GO

– Alteração da base, ou seja, criação da pasta, dentro do FileStream para a utilização da FileTable

--ALTERA PARA ACESSO NÃO TRANSACIONAL
ALTER DATABASE BlogFileTable SET FILESTREAM( NON_TRANSACTED_ACCESS = FULL, 
DIRECTORY_NAME = 'BlogFileTable') WITH NO_WAIT
GO

Aqui,voce ja deve poder visualisar se o acesso FileStream esta habilitado em sua base de dados, vide select:

--SELECT DE ACESSO NÃO TRANSACIONAL
SELECT DB_NAME(database_id), non_transacted_access, non_transacted_access_desc
FROM sys.database_filestream_options;

Todos os arquivos que iremos visualizar estara contido em uma tabela, obviamente, portanto, devemos criar esta tabela, que possui uma sintaxe curiosa, e um pouco diferente de um CREATE TABLE regular…

CREATE TABLE Documentos AS FileTable
    WITH ( 
          FileTable_Directory = 'BlogFileTable',
          FileTable_Collate_Filename = database_default
         );
GO

Agora, basta voce copiar e colar os arquivos no caminho especificado, que no meu caso, para o exemplo acima é: \\FABRIZZIO-PC\fabrizzio12ent\BlogFileTable\BlogFileTable

Caso voce não esteja conseguindo abrir a pasta, execute:

--VERIFICAÇÃO DA PASTA
SELECT FileTableRootPath ('Documentos', 2)

Ou seja, trocando “Documentos” pelo nome da sua tabela FileTable

O select nesta tabela pode e deve ser feito normalmente:

SELECT *
FROM Documentos

Aonde sera possivel encontrar N informações sobre o arquivo.

Outra curiosidade é a possibilidade de se criar diretorios, ou seja, alem de automatico, sua arquivos tambem pode ficar organizados!

SQL Server 2012 – LEAD e LAG

Primeiramente queria pedir desculpas pelo tempo em que não consegui postar nada, existem varias coisas acontecendo, o que impede minha total dedicação ao Blog, todo caso, não posso deixar de postar sobre algumas coisas bem legais!!!
Essa semana começei a estudar para as provas do SQL Server 2012, portanto, muito provavelmente meus proximos posts serão todos relacionados a tal.

Para este primeiro, gostaria de comentar sobre 2 funções bem simples, porem extremamente uteis chamadas LEAD e LAG.

Muito provavelmente voces ja passaram por situações aonde certa linha deve receber o valor de uma linha de baixo ou de cima, um exemplo classico é por exemplo:

Cidade KmInicial KmFinak
Cidade a 1 50
Cidade b 51 100
Cidade c 101 105

Em situações normais até o SQL Server 2008, voce seria obrigado, para resolver este problema, a:
1. Ou armazenar os valores iniciais e finais de cada cidade, o que é bem ruim, uma vez que estou seguindo a regra de que a

proxima cidade inicia em 1Km após a anterior, eu conseguiria tal valor.
2. Utilizando Self Joins, o que pode causar a consulta um pouco complexa, principalmente para iniciantes….

Porem, no SQL Server 2012, temos as funções LEAD e LAG (Como descrito acima….), porem, o que elas fazem?

LAG: Pega qualquer valor, de uma linha acima da atual, seus valores de entrada são obrigatoriamente o campo da tabela que voce quer, o numero de linhas acima que voce quer (Que em 99% da vezes sera 1, ou seja, a linha acima) e um valor default caso o mesmo não existe (Para quando ser a primeira linha por exemplo…)

LEAD: Possui os mesmos valores de entrada, porem, ao invez de pegarmos linha acima, podemos pegar linha abaixo.
Segue exemplo de TSQL

CREATE TABLE Analises
(
	Cidade VARCHAR(100),
	Total INT
)

INSERT INTO Analises VALUES
('São Paulo', 10),
('São Paulo', 7),
('São Paulo', 6),
('São Paulo', 3),
('Campinas', 15),
('Campinas', 10)

--LEAD
SELECT Cidade, Total, LEAD(Total, 1, 0) OVER(ORDER BY Total) As Proximo_Total
FROM Analises

--LAG
SELECT Cidade, Total, LAG(Total, 1, 0) OVER(ORDER BY Total) As Ultimo_Total
FROM Analises

Utilizando o MemoryStatus – 001

Sei que ja é um assunto bem batido, mas o gerenciamento de memoria do SQL Server sempre me deixa curioso e sempre existe algo diferente a ser comentado.

Ja tenho outros 2 posts sobre memoria, que podem ser vistos aqui e aqui.

Seguindo alguns posts do Fabricio Catae (Que pode ser visto aqui).
Sei tambem que tais informações ja existem em DMV´s (A partir do SQL Server 2005, é claro…), mas eu gosto deste comando, pois ele te traz uma gama enorme de informações…

Se executarmos o MEMORYSTATUS, veremos muitas opções, não irei aplicar nenhum filtro neste post, pois os mesmos podem ser facilmente encontrados na internet, então, de forma simples, no retorno do memorystatus, vamos buscar o que é interessante de se comentar neste primeiro post:

Buffer Pool:
Committed -> Aqui temos a informação de quantas paginas (8k) o SQL Server esta efetivamente utilizando.
Target -> O total que ele pode chegar, o Committed pode ser menor ou igual ao Target, mas nunca maior, ou seja, o SQL Server nunca ira utilizar mais memoria do que o real existente e disponivel.
Database -> Total de paginas de dados que o SQL Server possui em memoria.
Dirty -> Total de paginas de dados sujas* em memoria

Process/System Counts:
Available Physical Memory -> Memoria fisica disponivel no servidor, cuidado com este contador, se ele chegar a 0, quer dizer que toda sua memoria fisica foi esgotada, o que pode causar indisponibilidade de todos os outros serviços que rodam no servidor.
Percent of Committed Memory in WS -> Total percentual de memoria na memoria fisica, ou seja, de forma didatica, não “utilizando o disco como memoria”, o ideal é que este esteja sempre perto dos 100.

*Uma pagina suja possui esta nomenclatura quando seu conteudo em memoria esta diferente do original em disco, ou seja, a pagina foi alterada, e sera necessario um processo de CheckPoint (Que pode ser visto aqui) para limpa-las.

Exemplo pratico de utilização do comando MERGE

Um amigo meu veio me perguntar sobre algumas duvidas em relação ao comando MERGE do SQL Server, principalmente em relação a performance e sua utilização.

Abaixo segue o script que o enviei, assim como o ajudou, espero que possa ajudar outras pessoas tambem.

CREATE TABLE Funcionarios
(
	nm_Funcionario VARCHAR(100),
	pct_Comissao INT
)

CREATE TABLE Funcionarios2
(
	nm_Funcionario VARCHAR(100),
	pct_Comissao INT
)

CREATE TABLE LogTeste
(
	nm_Funcionario VARCHAR(100),
	Texto VARCHAR(100)
)

INSERT INTO Funcionarios VALUES
('Fabrizzio', 5),
('Caputo', 10),
('Antoniaci', 15)

INSERT INTO Funcionarios2 VALUES
('Giovanni', 5),
('Caputo', 20),
('Antoniaci', 25)



--Antes
SELECT * FROM Funcionarios
/*
Fabrizzio	5
Caputo		10
Antoniaci	15
*/

SELECT * FROM Funcionarios2
/*
Giovanni	5
Caputo		20
Antoniaci	25
*/

MERGE Funcionarios AS Target
USING (SELECT nm_Funcionario, pct_Comissao FROM Funcionarios2) As Source(Nome, Comissao)
ON (Target.nm_Funcionario = Source.Nome)
WHEN MATCHED THEN
	UPDATE SET Target.pct_Comissao = Source.Comissao
WHEN NOT MATCHED THEN
	INSERT (nm_Funcionario, pct_Comissao)
	VALUES (Source.Nome, Source.Comissao);
	
--DEPOIS
--Antes
SELECT * FROM Funcionarios
/*
Fabrizzio	5
Caputo		20
Antoniaci	25
Giovanni	5
*/

SELECT * FROM Funcionarios2
/*
Giovanni	5
Caputo	20
Antoniaci	25
*/

/*EM RELAÇÃO AO QUE FAZ

O merge é comando muito bom, disponivel (Se não me engano) desde o SQL Server 2005, o proposito dele é enxugar codificação
aonde com apenas um comando, voce consegue fazer N ações, como no exemplo acima que eu fiz:
	- Caso o funcionario não exista na tabela "Funcionario", o mesmo sera inserido.
	- Caso o mesmo ja exista, o pct_Comissao sera atualizado
Alem disso, é bem flexivel, a ponto de eu conseguir especificar algumas regras como:
	- Só atualize se o pct_Comissao for mais baixo
	- Atualize o Target ou o Source
	- Faça Match pelo Target ou Source ao invez de um match generico
O "problema" é que ele realmente não é dos comandos mais simples, alem de ter muitas opções, o que acaba confundindo muitas 

pessoas,
alem de algumas restrições que o fazem ser menos utilizado.

 EM RELAÇÃO A PERFORMANCE

O que meu codigo fez:
	- Inseriu novos e atualizou os ja existentes

No merge: 0,028126 de custo 
Sem merge: 0.0468959 de custo (Soma dos 2 abaixo)
Ou seja, houve sim uma queda de performance e o Merge se mostrou melhor.
Mas lembrando que performance é algo complicado e depende de indices, que por sua vez depende do percentual de atendimento 

condicional
em relação ao todo e algumas outras coisas.....
(Lembrando que estamos falando de uma tabela com 3 registros)
*/
--INSERIR NOVOS
INSERT INTO Funcionarios
SELECT b.nm_Funcionario, b.pct_Comissao
FROM Funcionarios a
RIGHT JOIN Funcionarios2 b
	ON (a.nm_Funcionario = b.nm_Funcionario)
WHERE a.nm_Funcionario IS NULL
--0,0300194
--ATUALIZAR ANTIGOS
UPDATE a
SET a.pct_Comissao = b.pct_Comissao
FROM Funcionarios a
INNER JOIN Funcionarios2 b
	ON (a.nm_Funcionario = b.nm_Funcionario)
--0,0168765

SELECT 0.0300194 + 0.0168765