我只是建立了一个由多个具有相同布局的表组成的日志系统。
每个数据源都有一个表。
对于日志查看器,我想
- 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
,然后再合并和排序行。
我真的以为是这样,但是EXPLAIN
在查询上运行告诉我子查询仍在搜索两个表。
EXPLAINing
子查询本身向我显示了所需的优化,但UNIONing
它们却没有。
我错过了什么?
我知道子查询中的ORDER BY
子句UNION
不带会被忽略LIMIT
,但是有一个限制。
编辑:
实际上,可能还会有没有account_id
条件的查询。
这些表已经存在,并已填充数据。布局可能会有所不同,具体取决于来源,因此我想让它们保持分开。此外,由于某种原因,日志记录客户端使用不同的凭据。
我必须在日志读取器和实际表之间保留一层。
以下是整个查询和第一个子查询的执行计划以及表布局的详细信息:
又为什么
—
ypercubeᵀᴹ
UNION DISTINCT
呢?无需在此处强制排序和区分,因为由于额外的标识列,结果在各个子查询中将有所不同。使用UNION ALL
。
除了@ypercube的建议外,我还有一个问题:将所有这些日志添加到同一表中,再加上列,会不会更好
—
dezso 2012年
source
?这样,您可以避免UNION
使用s并在所有数据中使用索引。
@ypercube实际上,可能还会有一些没有account_id条件的查询。该DISTINCT标志是之前尝试的孑遗和实际上是无用的,因为结果总是会有所不同,因为DISTINCT是dafualt行为。这些表已经存在,并已填充数据。无论如何,版式可能会有所不同,具体取决于来源,因此我想将它们分开。此外,由于某种原因,日志记录客户端使用不同的凭据。我必须在日志读取器和实际表之间保留一层。
—
卢卡斯2012年
可以,但是检查是否更改为
—
ypercubeᵀᴹ
UNION ALL
不同的执行计划。
(account_id, zeitpunkt)
。你有这样的索引吗?第二个最佳选择是(我认为)单个(zeitpunkt)
-但使用效率取决于行account_id=730
出现的频率。