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 / 106650
Accepted
ivan
ivan
Asked: 2015-07-11 15:52:36 +0800 CST2015-07-11 15:52:36 +0800 CST 2015-07-11 15:52:36 +0800 CST

'SELECT my_table.id' mais lento que 'SELECT my_table.*'

  • 772

Executando MySQL com InnoDB:

Tenho uma SELECT wide_table.*consulta que desejo refinar, SELECT wide_table.idpois é tudo o que o código de chamada precisa. Testando, descobri que o tempo de execução com *é mais rápido do que com id(embora o tempo para transferir o resultado pela rede seja mais rápido com a versão "refinada").

Por que isso seria o caso?

A consulta (com nomes alterados para proteger os inocentes) é:

SELECT
    `things`.*
FROM
    `things`
WHERE
    `things`.`active` = 1
        AND (owner_id IS NOT NULL
        AND owner_id > 0)
        AND ((`things`.`status` IN (0 , 1)
        OR `things`.`status` IS NULL))
        AND (date < '2015-07-11 00:00:00');

Há um índice composto em activee date, que está sendo usado em ambas as versões.

Para referência, a saída de SHOW CREATE TABLE(com colunas irrelevantes omitidas):

CREATE TABLE `things` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `active` tinyint(1) DEFAULT '0',
  `date` datetime DEFAULT NULL,
  `owner_id` int(11) DEFAULT '0',
  `status` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_things_on_active_and_date` (`active`,`date`),
  KEY `index_things_on_date` (`date`),
  KEY `index_things_on_owner_id` (`owner_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1862 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Limites

Depois de brincar um pouco com isso, descobri que a comparação é afetada pelo limite imposto à consulta. Com limites grandes, >200, a *versão relata um tempo de execução mais rápido. À medida que o limite diminui <200, a idversão ganha vantagem. Ainda não tenho certeza do que fazer com isso...

EXPLIQUE

A execução EXPLAINem ambas as versões da consulta gera uma saída idêntica, com select_type: SIMPLEe key: index_things_on_active_and_date.

mysql innodb
  • 1 1 respostas
  • 198 Views

1 respostas

  • Voted
  1. Best Answer
    RolandoMySQLDBA
    2015-07-12T16:45:28+08:002015-07-12T16:45:28+08:00

    O plano EXPLAIN para SELECT *e SELECT id, que você disse serem idênticos, seria separado pelo número de linhas acessadas. Como as linhas estão sendo acessadas? Através do index_things_on_active_and_dateíndice. O SIMPLEno EXPLAIN significa que é uma varredura. Em ambos os casos, é uma varredura de índice baseada active=1edate < '2015-07-11 00:00:00'

    Como ocorre a varredura de índice?

    • Como o índice escolhido possui activee date, a varredura do intervalo ocorreria a partir de duas colunas.
    • Veja a WHEREcláusula. Você está recuperando owner_ide statusverificando os valores. Isso requer que você acesse toda a linha.
      • SELECT *significa que você torna toda a linha parte do conjunto de resultados
      • SELECT idsignifica que você torna o id parte do conjunto de resultados

    Para onde isso está levando?

    • Em ambos os casos, você está lendo uma linha inteira para verificar duas colunas adicionais que não estão no índice.
    • O conjunto de resultados de cada consulta é uma linha inteira ou uma única coluna (id).
    • Deve levar algum tempo adicional para criar um conjunto de resultados menor. Por quê ? Chega um ponto em que um resultado mais longo de idvalores levaria mais tempo para ser construído do que para toda a linha que você lê de qualquer maneira. Você mesmo testou isso empiricamente e descobriu o seguinte:
      • < 200 rows-> SELECT idé mais rápido
      • > 200 rows-> SELECT *é mais rápido
      • = 200 rows-> SELECT ide SELECT *são quase iguais

    Há algo mais que você precisa saber sobre o InnoDB

    • O InnoDB armazena os dados de uma linha que são armazenados junto com as páginas de índice que compõem a PRIMARY KEY. Isso é conhecido como índice clusterizado (gen_clust_index)
    • Os índices não exclusivos armazenarão os campos de chave primária da linha junto com as entradas do índice.

    Isso informa que o índice index_things_on_active_and_daterealmente tem três colunas: 1) active, 2) date, 3) id​​.

    Você provavelmente está dizendo: Por que SELECT *correr é melhor assim SELECT id? (que é a pergunta original) Volta ao que eu disse: a cláusula WHERE está fazendo com que o Query Optimizer verifique colunas não indexadas statuseowner_id . Você está criando um trabalho adicional para verificar uma entrada de índice e algo da linha que está indexada.

    Se você criar este índice

    ALTER TABLE things
        ADD INDEX index_everything_and_kitchen_sink
        (active,date,owner_id,status)
    ;
    

    e execute as duas consultas, então você verá a vantagem, SELECT idnão importa quantas linhas você esteja acessando. Por quê ? Porque todas as colunas na cláusula WHERE são verificadas apenas no índice . Esse tipo de índice é chamado de índice de cobertura.

    Aqui estão alguns bons links sobre como cobrir índices

    • http://peter-zaitsev.livejournal.com/6949.html
    • http://www.mysqlperformanceblog.com/2006/11/23/covering-index-and-prefix-indexes/
    • http://ronaldbradford.com/blog/tag/covering-index/

    Eu mencionei esses links em algumas das minhas respostas:

    • Feb 10, 2012 Tempo de consulta extremamente longo inesperado (cerca de 5 minutos usando WHEN-INs aninhados)
    • Oct 17, 2012: Combinando colunas no índice
    • Jan 11, 2013: MySQL: Para usar o mecanismo MYISAM ou INNODB? (reviravolta na história incluída)
    • 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