Acabei de configurar um sistema de registro que consiste em várias tabelas com o mesmo layout.
Há uma tabela para cada fonte de dados.
Para o visualizador de logs, quero
- UNION todas as tabelas de log ,
- filtrá-los por conta ,
- adicione uma pseudo-coluna para identificação da fonte,
- classificá-los por tempo ,
- e limite-os para paginação .
Todas as tabelas contêm um campo chamado zeitpunkt
que é uma coluna de data / hora indexada.
Minha primeira tentativa foi:
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt AS zeit,
'hp' AS source FROM is_log AS l WHERE l.account_id = 730)
UNION
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt,
'ig' AS source FROM ig_is_log AS l WHERE l.account_id = 730)
ORDER BY zeit DESC LIMIT 10;
O otimizador não pode usar os índices aqui porque todas as linhas de ambas as tabelas são retornadas pelas subconsultas e classificadas após o UNION
.
Minha solução alternativa foi a seguinte:
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt AS zeit,
'hp' AS source FROM is_log AS l WHERE l.account_id = 730
ORDER BY l.zeitpunkt DESC LIMIT 10)
UNION
(SELECT l.id, l.account_id, l.vnum, l.count, l.preis, l.zeitpunkt,
'ig' AS source FROM ig_is_log AS l WHERE l.account_id = 730
ORDER BY l.zeitpunkt DESC LIMIT 10)
ORDER BY zeit DESC LIMIT 10;
Eu esperava que o mecanismo de consulta usasse os índices aqui, já que as duas subconsultas já deveriam ser classificadas e limitadas antes da UNION
, que depois mescla e classifica as linhas.
Eu realmente pensei que seria isso, mas a execução EXPLAIN
da consulta me diz que as subconsultas ainda pesquisam as duas tabelas.
EXPLAINing
as próprias subconsultas me mostram a otimização desejada, mas UNIONing
elas juntas não.
Perdi alguma coisa?
Eu sei que ORDER BY
cláusulas dentro de UNION
subconsultas são ignoradas sem a LIMIT
, mas há um limite.
Edit:
Na verdade, provavelmente também haverá consultas sem aaccount_id
condição.
As tabelas já existem e são preenchidas com dados. Pode haver alterações no layout, dependendo da fonte, então eu quero mantê-las divididas. Além disso, os clientes de log usam credenciais diferentes por um motivo.
Eu tenho que manter um tipo de camada entre os leitores de log e as tabelas reais.
Aqui estão os planos de execução para toda a consulta e a primeira subconsulta, bem como o layout da tabela em detalhes:
UNION DISTINCT
? Não há necessidade de forçar uma classificação e distinção lá, pois os resultados serão diferentes nas subconsultas, devido à coluna de identificação extra. Use UNION ALL
.
source
coluna? Dessa forma, você pode evitar se UNION
usar índices em todos os seus dados.
UNION ALL
produz um plano de execução diferente.
(account_id, zeitpunkt)
. Você tem esse índice? O segundo melhor seria (acho) o single(zeitpunkt)
- mas a eficiência, se usada, depende da frequência com que as linhasaccount_id=730
aparecem.