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 / 283439
Accepted
Hasan Can Saral
Hasan Can Saral
Asked: 2021-01-18 11:05:09 +0800 CST2021-01-18 11:05:09 +0800 CST 2021-01-18 11:05:09 +0800 CST

Como adiciono índices compostos do MySQL com desnormalização e JOINS?

  • 772

Tenho as seguintes tabelas:

CREATE TABLE base_event (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    created_by ... -- some columns
);

CREATE TABLE transaction_events (
    event_id BIGINT UNSIGNED NOT NULL,
    transaction_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    merchant_id BIGINT UNSIGNED NULL DEFAULT NULL,   
    merchant_city VARCHAR (...) NULL DEFAULT NULL, -- Denormalize
    customer_id BIGINT UNSIGNED NULL DEFAULT NULL,
    customer_ip_address VARCHAR(...) NULL DEFAULT NULL, -- Denormalize
    ...
    FOREIGN KEY (event_id) REFERENCES base_event(id),
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    FOREIGN KEY (merchant_id) REFERENCES merchants(id),
);

CREATE TABLE customers (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    customer_ip_address VARCHAR(...) NULL DEFAULT NULL,
    ...
);

CREATE TABLE merchants (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ...
);

E meu SELECT:

(SELECT t.*, c.name AS customer_name ...
FROM transaction_events t
JOIN customers c ON t.customer_id = c.id
JOIN merchants m ON t.merchant_id = m.id
WHERE t.customer_ip_address = 'abc' AND t.transaction_time > 'abc')
UNION DISTINCT
(SELECT t.*, c.name AS customer_name ...
FROM transaction_events t
JOIN customers c ON t.customer_id = c.id
JOIN merchants m ON t.merchant_id = m.id
WHERE t.merchant_city = 'abc' AND t.transaction_time > 'abc')

E meus índices são:

ALTER TABLE transaction_events 
ADD INDEX index_1 (customer_ip_address, transaction_time),
ADD INDEX index_2 (merchant_city, transaction_time);
  1. Minha consulta está neste formulário para evitar arquivos OR.
  2. Eu desnormalizei até certo ponto por causa dos índices.
  3. Não preciso referenciar minha base_eventtabela para esta consulta.
  4. A relação com transaction_eventsto customerse merchantsnão é 1-para-1, mas 1-para-0-ou-1.

Minhas perguntas:

  1. Eu posso me livrar do curinga, mas transaction_eventstem cerca de 20 colunas (ajudaria a criar mais índices para acelerar a consulta?
  2. Preciso colocar outros índices compostos (que potencialmente referenciam meus FKs) para melhorar ainda mais essa consulta?
mysql index
  • 2 2 respostas
  • 92 Views

2 respostas

  • Voted
  1. J.D.
    2021-01-18T11:26:08+08:002021-01-18T11:26:08+08:00

    Você precisa de todas as 20 colunas de transaction_events? Caso contrário, eliminar *e especificar apenas as colunas de que você precisa não apenas reduz a quantidade de dados que você está recuperando de uma só vez, mas também reduz as chances de um plano de consulta abaixo do ideal. É possível que o plano de consulta gerado varie com base nas colunas da sua SELECTcláusula.

    Você pode testar a adição de um índice no customer_idcampo e outro índice no merchant_idcampo para suas JOINcláusulas e ver se isso melhora o desempenho e produz um plano de consulta melhor. Mas isso exigirá testes e comparação do EXPLAIN para cada caso.

    • 1
  2. Best Answer
    Rick James
    2021-01-18T11:31:04+08:002021-01-18T11:31:04+08:00

    As WHEREcláusulas referem-se a t, portanto, é muito provável que o Optimizer comece com tem cada uma SELECT. Você tem os índices ideais para eles.

    Em seguida, ele precisa acessar as outras duas tabelas ( merchantse customers) e obter 1 (ou 0) linha delas. Essas tabelas têm o índice ótimo para o JOIN, ou seja, PRIMARY KEY(id)em cada caso. (Os FKs não desempenham nenhum papel nesta consulta.)

    t.*pode atrasar as coisas se estiver buscando TEXTcolunas grandes que você ignora.

    Como você precisa de todas as colunas, a única ineficiência possível é se cada uma SELECTestiver buscando a mesma linha de forma redundante, apenas para ser desduplicada por UNION DISTINCT. Acho que não vale a pena corrigir esse problema. (A correção seria UNIONapenas encontrar e desduplicar t.id; depois juntar novamente para tobter as outras 19 colunas. O custo do trabalho extra pode superar o benefício; não posso dizer.)

    • 1

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