Fala, gente… beleza? Agora estou escrevendo sobre o SQL Server para o MXStudio. É o banco de dados da Microsoft e (na minha opinião) o melhor que existe hoje no mercado.
Com que dados eu fundamento isso? Experiência, fiote… experiência… Trabalhei alguns anos com Oracle, já desenvolvi em/para Access e MySQL, além do DB2 e Sybase. Mas eu gostei mesmo é do SQL Server.
Vamos ao assunto do post:
Um recurso que melhora muito a velocidade de acesso aos dados armazenados é o tal de índice. Já tinha publicado esse post no meu site, mas vale a pena rever pois é muito atual.
Primeiro: qual a função de um índice? Melhorar o desempenho em consultas.
Segundo: quais os tipos de índice que temos no SQL Server? Dois: CLUSTERED e NON-CLUSTERED.
Terceiro: o que é um índice? É uma estrutura de árvore (balanceada – um tipo de árvore binária).
Quarto: é mais rápido que pesquisar na tabela, mesmo? Agora sim apareceu A pergunta… vamos começar por ela.
Inicialmente, precisamos definir árvore binária: uma estrutura formada por nós (vértices) e por folhas. Os nós são para determinar a localização de uma informação qualquer (na figura - uma representação simplificada - abaixo, 1-4, 1-2 e 3-4 são nós). As folhas (1, 2, 3 e 4, na figura abaixo) são as informações armazenadas.

Imagine, agora, que minha tabela tenha somente 2 registros: olhando para um deles saberei se é aquele que quero, ou não.
Se tiver 4 registros, devo procurar um máximo de 2 vezes. Veja a figura acima:
Extrapolando, podemos montar uma tabela como abaixo, já que sabemos ser o número de pesquisas necessárias igual ao expoente a que 2 deve ser elevado para “dar” a quantidade de registros:
| QTD REGISTROS | LEITURAS | |
|---|---|---|
| até 2 | 1 | 2 = 21 |
| até 4 | 2 | 4 = 22 |
| até 8 | 3 | 8 = 23 |
| … | … | … |
| até 1.024 | 10 | 1.024 = 210 |
| até 1.048.576 | 20 | 1.048.576 = 220 |
Mas, onde esses índices são gravados? Ops… Onde qualquer dado (tabela ou índice) é gravado? A resposta é: numa estrutura chamada PAGE. Uma page (página de dados) tem 8kB (8.192 bytes). Desse valor, tiramos 96 bytes, que são usados para endereçamento interno. O que sobra (8.096 bytes) está disponível para armazenamento de dados.
Uma page pode conter dados de tabelas ou de índices. Outra coisa: uma page somente pode conter dados de uma ÚNICA tabela ou de um ÚNICO índice.
Agora, sim. Podemos dizer que:
Para os exemplos seguintes, usaremos a tabela criada com o bloco de comandos abaixo:
CREATE DATABASE EXEMPLO_INDICE
GO
USE EXEMPLO_INDICE
CREATE TABLE PESSOA
(
COD INT NOT NULL,
NOME VARCHAR(50),
SEXO CHAR(1)
)
Inserimos alguns registros:
INSERT INTO PESSOA VALUES(1, ‘BRUNO’, ‘M’)
INSERT INTO PESSOA VALUES(2, ‘NETINHO’, ‘M’)
INSERT INTO PESSOA VALUES(3, ‘PEDRO’, ‘M’)
INSERT INTO PESSOA VALUES(4, ‘AGNALDO’, ‘M’)
INSERT INTO PESSOA VALUES(5, ‘MARIA’, ‘F’)
INSERT INTO PESSOA VALUES(6, ‘ANA MARIA’, ‘F’)
INSERT INTO PESSOA VALUES(7, ‘MARIANA’, ‘F’)
INSERT INTO PESSOA VALUES(8, ‘MARINA’, ‘F’)
Agora, vamos fazer alguns selects e ver qual é o plano de execução gerado. Eita nóis… O que é um plano de execução? Plano de execução é um “mapa” gerado pelo mecanismo relacional que informa ao mecanismo de armazenamento onde ler ou gravar no disco, se vai acessar a tabela diretamente ou se vai usar um índice, se a pesquisa é feita por seek ou por scan.
De novo: eita ferro!!! O que são esses mecanismos? Quando instalamos o SQL Server e iniciamos o serviço MSSQLSERVER, temos na memória três elementos:
Como vejo um plano de execução? Basta habilitar sua apresentação através das teclas de atalho [CTRL] + [M] ou acessar a opção [Include Actual Execution Plan] do menu [Query]. Para testar, podemos selecionar alguns dados da tabela, usando:
SELECT * FROM PESSOA
O plano de execução apresentado é:

Onde Table Scan é o operador que significa que foi feito um acesso sequencial a todos os elementos da tabela Pessoa.
Para qualquer um dos comandos o plano de execução gerado é o mesmo:
SELECT * FROM PESSOA WHERE COD = 1
SELECT NOME FROM PESSOA
SELECT NOME FROM PESSOA WHERE NOME = ‘AGNALDO’
SELECT COD, NOME FROM PESSOA WHERE NOME = ‘AGNALDO’
SELECT * FROM PESSOA WHERE NOME = ‘AGNALDO’
Agora, vamos criar um índice do tipo non-clustered para o campo NOME da tabela, usando o comando:
CREATE NONCLUSTERED INDEX INDEX_PESSOA_NOME ON PESSOA(NOME)
Executando os comandos abaixo, temos planos de execução (uso de operadores) diversos:
SELECT * FROM PESSOA
–-TABLE SCAN
SELECT * FROM PESSOA WHERE COD = 1
–-TABLE SCAN
SELECT NOME FROM PESSOA
–-INDEX SCAN
SELECT NOME FROM PESSOA WHERE NOME = ‘AGNALDO’
–-INDEX SEEK
SELECT COD, NOME FROM PESSOA WHERE NOME = ‘AGNALDO’
–-TABLE SCAN
SELECT * FROM PESSOA WHERE NOME = ‘AGNALDO’
–-TABLE SCAN
Criamos agora, um índice clustered, para o campo COD da tabela:
CREATE CLUSTERED INDEX INDEX_PESSOA_COD ON PESSOA(COD)
E executamos os mesmos comandos:
SELECT * FROM PESSOA
–-CLUSTERED INDEX SCAN
SELECT * FROM PESSOA WHERE COD = 1
–-CLUSTERED INDEX SEEK
SELECT NOME FROM PESSOA
–-INDEX SCAN
SELECT NOME FROM PESSOA WHERE NOME = ‘AGNALDO’
–-INDEX SEEK
SELECT COD, NOME FROM PESSOA WHERE NOME = ‘AGNALDO’
–-INDEX SEEK
SELECT * FROM PESSOA WHERE NOME = ‘AGNALDO’
–-CLUSTERED INDEX SCAN
… continua …
Pingback: Índices no SQL Server - parte 02 - Geral | MXStudio
Caramba, professor. Até aqui seu SQL está chegando? Tá ficando bom nisso aí, hein. Mas um dia eu chego aí onde vc tá.
Abraços e boa sorte…
Leonardo Breda (um de seus ex-alunos da impacta).
Ah, e ai,… quando sai o seu livro?
Gosrei bastante olha você tem o flash cs4 portatil que podese me enviar.
O SQL Server é um bom banco…. mas está milhares de anos luz longe de ser o melhor banco do mercado… sofro todos os dias com alguma mania esquesita dessa porcaria.