MySQL:在内部查询中使用“ORDER BY”优化UNION

我只是建立了一个由多个具有相同布局的表组成的日志系统.

每个数据源都有一个表.

对于日志查看器,我想

> UNION所有日志表,
>按帐户过滤,
>添加伪列以识别源,
>按时间排序,
>并限制它们进行分页.

所有表都包含一个名为zeitpunkt的字段,该字段是索引日期/时间列.

我的第一次尝试是:

(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;

优化器不能在此使用索引,因为子表中的所有行都由子查询返回并在UNION之后排序.

我的解决方法如下:

(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;

我期望查询引擎会在这里使用索引,因为两个子查询应该在UNION之前进行排序和限制,然后UNION合并并对行进行排序.

我真的以为这就是它,但在查询上运行EXPLAIN告诉我子查询仍然搜索两个表.

解释子查询本身向我展示了所需的优化,但是将它们联合起来却没有.

我错过了什么?

我知道UNION子查询中的ORDER BY子句在没有LIMIT的情况下被忽略,但是有一个限制.

编辑:
实际上,可能还会有没有account_id条件的查询.

这些表已经存在并且填充了数据.布局可能会有变化,具体取决于来源,因此我希望将它们分开.此外,日志记录客户端出于某种原因使用不同的凭据.

我必须在日志阅读器和实际表之间保留一种层.

以下是整个查询和第一个子查询以及表格布局的执行计划:

https://gist.github.com/ca8fc1093cd95b1c6fc0

最佳答案
出于好奇,你能试试这个版本吗?它可能会欺骗优化器使用子查询单独使用的相同索引:

SELECT *
FROM
(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) 
    AS a

UNION ALL

SELECT *
FROM
(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)
    AS b

ORDER BY zeit DESC LIMIT 10;

我仍然认为你可能拥有的最佳指数是复合(account_id,zeitpunkt).它会快速产生10行,并且不需要任何技巧.

转载注明原文:MySQL:在内部查询中使用“ORDER BY”优化UNION - 代码日志