AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 205182
Accepted
Eaten by a Grue
Eaten by a Grue
Asked: 2018-04-28 07:31:57 +0800 CST2018-04-28 07:31:57 +0800 CST 2018-04-28 07:31:57 +0800 CST

Ordem do índice composto

  • 772

Suponha que eu tenha uma consulta como:

SELECT *
FROM table_a
    JOIN table_b USING (id)
WHERE table_b.column = 1

Eu tenho um índice ativado ide um índice ativado, columnmas geralmente adiciono um índice composto com ambos, o que pode melhorar a eficiência de consultas como essa. Minha pergunta é sobre a ordem das colunas no índice. Por tentativa e erro, descobri que às vezes o DBMS prefere o índice unido primeiro e às vezes prefere o WHEREíndice primeiro.

Na consulta acima, existe uma regra rígida e rápida que eu possa seguir para saber qual ordem de chave funcionará melhor?

Normalmente, apenas adiciono os dois índices, executo EXPLAINa consulta e verifico qual é o preferido, depois removo o outro. Mas esse processo parece que pode ser melhorado por uma melhor compreensão da lógica envolvida na determinação da ordem do índice.

mysql optimization
  • 3 3 respostas
  • 1714 Views

3 respostas

  • Voted
  1. Rick James
    2018-05-19T11:41:15+08:002018-05-19T11:41:15+08:00

    Para esta consulta

    SELECT *
    FROM table_a
        JOIN table_b USING (id)
    WHERE table_b.column = 1
    

    A maneira ideal é executá-lo é

    1. A WHEREcláusula fornece alguma filtragem, então vamos fazer uso dela. Ou seja, tenha um índice table_b começando com column . (Mais tarde, discutiremos se devemos torná-lo composto.) Assim, o Otimizador usará esse índice para encontrar linha(s) de table_b.
    2. Para cada uma dessas linhas, JOINpara table_a. (Observe que JOIN, not LEFT JOINestá sendo usado; LEFT JOINé uma história diferente.)
    3. Para acessar table_a, é necessário um índice começando com id. (Nota: USING(id)significa table_a.id = table_b.id.)

    Até agora, temos

    b:  INDEX(column)
    a:  INDEX(id)   -- though it probably exists as PRIMARY KEY(id)
    

    Cobertura?

    Não sabemos quais outras colunas existem nas duas tabelas. Se houver muito poucas colunas, pode ser tentador criar um índice de "cobertura". Este é um índice que contém todas as colunas necessárias em qualquer lugar do arquivo SELECT. O benefício é alguma aceleração de desempenho ao olhar apenas no BTree do índice e não ter que tocar no BTree de dados.

    Pois table_b, seria tentador dizer INDEX(column, id). Isso seria bom (e 'cobrindo') se houvesse apenas essas duas colunas. Mas provavelmente há mais colunas. Então, provavelmente INDEX(column)é tudo o que vale a pena fazer.

    Para table_a, suponho que idseja o PRIMARY KEY(que é, por definição, único e um índice). Então, nada mais é necessário lá.

    Bottom line : Use os dois índices de coluna única listados acima.

    E este exemplo não exemplifica nada sobre índices "compostos". Para saber mais sobre isso, veja

    Cardinalidade e intervalo
    Cardinalidade e índice composto
    de uma coluna Livro de
    receitas de indexação

    mas muitas vezes eu adiciono um índice composto com ambos que podem melhorar a eficiência de consultas como esta ...

    Melhor exemplo

    Como eu disse, seu exemplo não exemplifica a pergunta. Então, vou tentar responder "Quando devo usar um índice composto"? Existem muitos casos (veja os links); Vou lhe dar um caso simples.

    WHERE x = 1
      AND y > 2
    

    As características relevantes são:

    • xe yestão na mesma tabela. (Não é possível criar um índice em duas tabelas.)
    • ANDé usado. ( ORnão pode ser otimizado.)
    • Um dos testes é com =. (Composto não ajudará se ambos forem intervalos.)
    • yé um "intervalo" (exemplos: y>2, y LIKE 'm%', y BETWEEN ... AND ...).

    A regra geral é :

    1. Coloque todas as =colunas primeiro ( xno meu exemplo)
    2. Coloque uma coluna de intervalo por último ( y)

    Ou seja, você deve encomendá-lo INDEX(x,y).

    Para WHERE x = 1 AND y = 2(ambos =), não importa se você tem INDEX(x,y)ou INDEX(y,x).

    Outro detalhe : Com ENGINE=InnoDB, as PRIMARY KEYcolunas são implicitamente anexadas a cada chave secundária. Portanto, seu INDEX(column)é o mesmo que INDEX(column, id). Mas este fato não desempenha um papel nesta discussão.

    Percebo que estou discordando de outras respostas aqui (e em outros lugares), mas mantenho minha posição.

    • 5
  2. Best Answer
    Hannah Vernon
    2018-04-28T09:47:26+08:002018-04-28T09:47:26+08:00

    Uma boa regra geral é tornar a coluna inicial em um índice composto o mais seletivo possível. Uma boa maneira de imaginar isso é com a analogia da lista telefônica: imagine que você precisa encontrar alguém na lista telefônica e há dois índices... o primeiro é Sobrenome, Nome. O segundo é FirstName, LastName. Qual índice você usaria para encontrar alguém chamado John Xilofone? Certamente você usaria o índice LastName, Firstname, pois há muito poucas entradas de Xilofone e levará muito menos tempo do que procurar em todas as entradas de John uma com o sobrenome de Xilofone.

    Portanto, se idfor altamente seletivo e columntiver baixa seletividade, você deseja que o índice seja (id, column), mas se columntiver alta seletividade e idbaixa seletividade, provavelmente se beneficiará de ter o índice definido como (column, id).

    Você pode ver um índice (column, id)sendo usado se estiver unindo duas tabelas quando resultar idem um número substancialmente reduzido de linhas que precisam ser unidas.where column = xx

    • 4
  3. Jack Douglas
    2018-05-19T05:59:51+08:002018-05-19T05:59:51+08:00

    Na consulta acima, existe uma regra rígida e rápida que eu possa seguir para saber qual ordem de chave funcionará melhor?

    No exemplo que você deu, sua melhor aposta é não ter um índice composto se você estiver livre para alterar a ordem de junção:

    create table table_a(id integer, dummy_a integer);
    create index index_a on table_a(id);
    create table table_b(id integer, col integer, dummy_b integer);
    create index index_b on table_b(col);
    
    explain select * from table_b join table_a using(id) where table_b.col=1;
    
    identificação | select_type | mesa | divisórias | tipo | chaves_possíveis | chave | key_len | ref | linhas | filtrado | Extra      
    -: | :---------- | :------ | :------------- | :--- | :------------ | :------ | :------ | :-------------------------- | ---: | -------: | :----------
     1 | SIMPLES | tabela_b | nulo        | ref | index_b | index_b | 5 | const | 1 | 100,00 | Usando onde
     1 | SIMPLES | tabela_a | nulo        | ref | index_a | index_a | 5 | fiddle_YRFDITQONPXNRMDBQSYV.table_b.id | 1 | 100,00 | nulo       
    

    db<>fique aqui

    • 2

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve