Eu tenho lido composite indexes
e estou um pouco confuso sobre pedidos. Esta documentação (pouco menos da metade do caminho) diz
Em geral, você deve colocar a coluna que se espera que seja usada com mais frequência primeiro no índice.
No entanto, logo após ele diz
crie um índice composto colocando a coluna mais seletiva em primeiro lugar; isto é, a coluna com mais valores.
A Oracle também diz aqui em outras palavras
Se todas as chaves forem usadas nas cláusulas WHERE com a mesma frequência, ordenar essas chaves da mais seletiva para a menos seletiva na instrução CREATE INDEX melhorará o desempenho da consulta.
No entanto, encontrei uma resposta SO que diz diferentemente. Diz
Organize as colunas com a coluna menos seletiva primeiro e a coluna mais seletiva por último. No caso de uma ligação de empate com a coluna que é mais provável de ser usada sozinha.
A primeira documentação que referenciei diz que você deve primeiro usar os mais usados, enquanto a resposta do SO diz que isso deve ser apenas para desempate. Então eles também diferem na ordem.
Esta documentação também fala skip scanning
e diz
A varredura de ignorar é vantajosa se houver poucos valores distintos na coluna inicial do índice composto e muitos valores distintos na chave não-líder do índice.
Outro artigo diz
A coluna de prefixo deve ser a mais discriminante e a mais usada nas consultas
que eu acredito que mais discriminatório significaria mais distinto.
Toda essa pesquisa ainda me leva à mesma pergunta; A coluna mais seletiva deve ser a primeira ou a última? A primeira coluna deve ser a mais usada e a mais seletiva em um tie-break?
Esses artigos parecem estar se contradizendo, mas oferecem alguns exemplos. Pelo que reuni, parece ser mais eficiente least selective column
que seja o primeiro a ordenar se você está antecipando Index Skip Scans
. Mas não tenho muita certeza se isso está correto.
fonte
Respostas:
De AskTom
Um dos argumentos para organizar colunas no índice composto na ordem dos menos discriminantes (valores menos distintos) para os mais discriminantes (valores mais distintos) é para a compactação da chave de índice.
De acordo com as estatísticas do índice, o primeiro índice é mais compressível.
Outra é como o índice é usado em suas consultas. Se suas consultas usam principalmente
col1
,Por exemplo, se você tiver consultas como
select * from t where col1 = :a and col2 = :b;
select * from t where col1 = :a;
-então
index(col1,col2)
teria um desempenho melhor.Se suas consultas costumam ser usadas
col2
,select * from t where col1 = :a and col2 = :b;
select * from t where col2 = :b;
-então
index(col2,col1)
teria um desempenho melhor. Se todas as suas consultas sempre especificarem ambas as colunas, não importa qual coluna será a primeira no índice composto.Em conclusão, as principais considerações na ordenação de colunas do índice composto são a compactação da chave de índice e como você usará esse índice em suas consultas.
Referências:
fonte
O mais seletivo primeiro é útil apenas quando esta coluna está na cláusula WHERE real.
Quando o SELECT é de um grupo maior (menos seletivo) e, possivelmente, de outros valores não indexados, um índice com colunas menos seletivas ainda pode ser útil (se houver um motivo para não criar outro).
Se houver uma tabela ADDRESS, com
COUNTRY CITY STREET, outra coisa ...
a indexação STREET, CITY, COUNTRY produzirá as consultas mais rápidas com o nome de uma rua. Mas, consultando todas as ruas de uma cidade, o índice será inútil e a consulta provavelmente fará uma verificação completa da tabela.
A indexação de PAÍS, CIDADE, RUA pode ser um pouco mais lenta para ruas individuais, mas o índice pode ser usado para outras consultas, selecionando apenas por país e / ou cidade.
fonte
Ao escolher a ordem da coluna do índice, a principal preocupação é:
Existem predicados (igualdade) nessa coluna nas minhas consultas?
Se uma coluna nunca aparecer em uma cláusula where, não vale a pena indexar (1)
OK, então você tem uma tabela e consultas em cada coluna. Às vezes mais de um.
Como você decide o que indexar?
Vejamos um exemplo. Aqui está uma tabela com três colunas. Um contém 10 valores, outros 1.000, os últimos 10.000:
Estes são números deixados com zeros. Isso ajudará a esclarecer mais tarde a compactação.
Então você tem três consultas comuns:
O que você indexa?
Um índice com apenas alguns valores é apenas marginalmente melhor do que uma verificação completa da tabela:
Portanto, é improvável que valha a pena indexar por conta própria. As consultas em lots_vals retornam algumas linhas (apenas 1 neste caso). Portanto, isso definitivamente vale a pena indexar.
Mas e as consultas nas duas colunas?
Você deve indexar:
OU
Truque de pergunta!
A resposta é nenhuma.
Certamente few_vals é uma string longa. Assim, você pode obter uma boa compactação. E você (pode) obter uma verificação de índice para as consultas usando (poucos_valos, lotes_valores) que possuem apenas predicados em lotes_valores. Mas não estou aqui, mesmo que ele tenha um desempenho notavelmente melhor que uma verificação completa:
Você gosta de jogar? 2)
Então você ainda precisa de um índice com lotes_valos como a coluna principal. E, pelo menos nesse caso, o índice composto (poucos, lotes) realiza a mesma quantidade de trabalho que um em apenas (lotes)
Haverá casos em que o índice composto economiza 1-2 IOs. Mas vale a pena ter dois índices para essa economia?
E há outro problema com o índice composto. Compare o fator de cluster para os três índices, incluindo LOTS_VALS:
Observe que o fator de agrupamento para poucos_ lotes é 10x maior que para lotes e lotes_fundos! E isso está em uma tabela de demonstração com cluster perfeito para começar. Nos bancos de dados do mundo real, o efeito provavelmente será pior.
Então, o que há de tão ruim nisso?
O fator de agrupamento é um dos principais fatores que determinam o quão "atraente" é um índice. Quanto maior, menor a probabilidade de o otimizador escolher. Especialmente se os lotes_vals não forem realmente únicos, mas ainda assim normalmente tiverem poucas linhas por valor. Se você tiver azar, isso pode ser suficiente para fazer o otimizador pensar que uma verificação completa é mais barata ...
OK, portanto, índices compostos com poucos valores e muitos valores têm apenas benefícios de caso de borda.
E as consultas que filtram alguns valores e muitos valores?
Os índices de colunas únicas oferecem apenas pequenos benefícios. Mas combinados, eles retornam poucos valores. Portanto, um índice composto é uma boa ideia. Mas qual o caminho?
Se você colocar alguns em primeiro lugar, compactar a coluna principal tornará essa menor
Com menos valores diferentes na coluna principal, compacta melhor. Portanto, há um pouco menos de trabalho para ler este índice. Mas apenas um pouco. E ambos já são um bom pedaço menor que o original (redução de 25% no tamanho).
E você pode ir além e comprimir todo o índice!
Agora os dois índices estão de volta ao mesmo tamanho. Observe que isso tira proveito do fato de que há uma relação entre poucos e muitos. Novamente, é improvável que você veja esse tipo de benefício no mundo real.
Até agora, falamos apenas sobre verificações de igualdade. Geralmente, com índices compostos, você terá uma desigualdade em relação a uma das colunas. por exemplo, consultas como "obter pedidos / remessas / faturas para um cliente nos últimos N dias".
Se você possui esses tipos de consultas, deseja a igualdade na primeira coluna do índice:
Observe que eles estão usando o índice oposto.
TL; DR
1: Em alguns casos, pode valer a pena incluir uma coluna em um índice, se isso significa que todas as colunas da sua consulta estão no índice. Isso permite uma verificação apenas do índice, para que você não precise acessar a tabela.
2: se você estiver licenciado para Diagnóstico e Ajuste, poderá forçar o plano a ignorar a varredura com o SQL Plan Management
ADDEDNDA
PS - os documentos que você citou são do 9i. Isso é realmente velho. Eu ficaria com algo mais recente
fonte
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
realmente comum? O Oracle não permite a sintaxeselect count (distinct few_vals, many_vals, lots_vals )
- que não faz concatenação de string, não precisa que as colunas sejam do tipo texto e não depende da ausência de:
caractere?count ( distinct x, y, z )
no Oracle. Portanto, você precisa fazer uma subconsulta distinta e contar os resultados ou uma concatenação como a acima. Eu só fiz isso aqui para forçar um acesso à tabela (em vez de indexar apenas scan) e só tem uma linha no resultadoHá mais elementos de consulta que contribuem para a decisão final sobre o que um Índice Composto deve iniciar e / ou conter além da seletividade da coluna.
por exemplo:
">,> =, <, <="
para manter a conversa relevante, minha resposta abaixo se aplica à seguinte situação:
sequência"
Na minha experiência, é sobre isso que o DBA deve estar atento.
1) Se eu criar um índice com a coluna mais seletiva sendo a primeira, mas essa coluna não for realmente usada pela maioria das consultas nessa tabela, será inútil para o mecanismo db.
2) Se eu criar um índice com a coluna mais usada em uma consulta, sendo a primeira no índice, mas a coluna tiver baixa seletividade, o desempenho da minha consulta também não será bom.
Vou listar as colunas usadas principalmente em 90% das consultas da tabela. Em seguida, coloque aqueles somente da ordem da maior cardinalidade à menor cardinalidade.
Usamos índices para melhorar o desempenho da consulta de leitura e esse fluxo de trabalho (tipos de consulta de leitura) deve apenas conduzir a criação do índice. De fato, à medida que os dados aumentam (bilhões de linhas), o índice compactado pode economizar armazenamento, mas com certeza prejudica o desempenho da consulta de leitura.
fonte
Em teoria, a coluna mais seletiva produz a pesquisa mais rápida. Mas, no trabalho, acabei encontrando uma situação em que temos um índice composto de 3 partes com a parte mais seletiva primeiro. (data, autor, editora, digamos, nessa ordem, a tabela monitora as postagens) e eu tenho uma consulta que usa todas as três partes. O Mysql usa como padrão o índice author onlny, ignorando o índice composto que contém a empresa e a data, apesar de eles estarem presentes na minha consulta. Usei o índice de força para usar o composto e a consulta realmente ficou mais lenta. Por que isso aconteceu? Eu direi a você:
Eu estava selecionando um intervalo na data, portanto, apesar da data ser altamente seletiva, o fato de estarmos usando-o para varreduras de intervalo (mesmo que o intervalo seja relativamente curto, 6 meses em 6 anos de dados) tornaram o composto prejudicial para mysql. Para usar o composto nesse caso em particular, o mysql precisa capturar todos os artigos escritos desde o ano novo e depois descobrir quem é o autor e, como o autor não escreveu tantos artigos em comparação com outros autores, o mysql preferiu apenas encontrar esse autor. .
Em outro caso, a consulta foi muito mais rápida no composto, quando um autor era muito popular e possuía a maioria dos registros, classificando por data. Mas o mysql não detectou automaticamente esse caso, eu tive que forçar o índice ... Então, você sabe, isso varia. As varreduras de intervalo podem tornar sua coluna seletiva inútil. A distribuição dos dados pode gerar casos em que as colunas são mais seletivas para diferentes registros ...
O que eu faria de diferente é mudar a data (que, novamente, em teoria, é a mais seletiva) para a direita, pois sei que vou fazer uma varredura de faixa agora e isso faz a diferença.
fonte
WHERE (date BETWEEN @x AND @y) AND (author = @a) AND (publishing company = @p)
, em seguida, um índice em(author, publishing_company, date)
ou(publishing_company, author, date)
seria melhor e seria usada - sem forçar.Casos diferentes para diferentes situações. Conheça seu objetivo; crie seus índices e execute planos de explicação para cada um e você terá sua melhor resposta para sua situação.
fonte
Da ordem da coluna no Índice em Ask Tom:
Concordo que precisamos ordenar colunas com base na cláusula where, mas a declaração "(a seletividade de a ou b não conta)" não está correta.) ". As colunas mais seletivas devem liderar se a primeira função for satisfeita ("cláusula where")
fonte