MySQL UNION LIMIT的性能

Nic*_*ick 4 mysql

我有两个不同的MySQL表,它们都包含时间序列数据(两者都包含'timestamp'列).除了'timestamp'列之外,这两个表除了'client_id'列之外不共享任何常用功能.

table_a
- id
- client_id
- timestamp
- ...

table_b
- id
- client_id
- timestamp
- ...
Run Code Online (Sandbox Code Playgroud)

两个表都在(client_id,timestamp)上建立索引.

我正在尝试将这两个表组合成一个分页的时间序列.要具体,我的意思是说我试图加载N条记录(与M的偏移量)从联盟table_atable_b由有序timestamp.

我尝试用这样的语句做到这一点:

(SELECT 'a', id FROM table_a WHERE client_id=1) UNION (SELECT 'b', id FROM table_b WHERE client_id=1) ORDER BY timestamp LIMIT 100;
Run Code Online (Sandbox Code Playgroud)

不幸的是,结果查询似乎抓住了两个表中的所有匹配行,组合,然后应用LIMIT.

请注意,针对各个表的查询非常快:

SELECT 'a', id FROM table_a WHERE client_id=1 ORDER by timestamp LIMIT 100
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来索引表或编写UNION查询?

Fra*_*ila 5

您无法在此处充分利用索引,因为两个单独的表中有两个单独的索引.

您可以为每个单独的选择添加限制,但这仅适用于第一页,而不适用于偏移.

如果您愿意放弃"页面"限制加偏移的要求,您可以对其他一些绝对(而不是相对)方式进行分页,例如按天.例如:

(SELECT 'a', id, timestamp FROM table_a WHERE client_id=1 AND timestamp BETWEEN '2014-04-18 00:00:00' AND '2014-04-18 23:59:59')
UNION
(SELECT 'b', id, timestamp FROM table_b WHERE client_id=1 AND timestamp BETWEEN '2014-04-18 00:00:00' AND '2014-04-18 23:59:59')
ORDER BY timestamp;
Run Code Online (Sandbox Code Playgroud)

但是,您的数据也可能未完全规范化,并且table_a和table_b的公共属性应位于第三个表中.此模式称为"连接表继承".

例如:

table_common
- id
- type ('a' or 'b')
- client_id
- timestamp
- primary key: (id, type) if id is not unique.
- index: (client_id, timestamp)

table_a
- id (same value as in table_common)
...

table_b
- id (same value as in table_common)
...
Run Code Online (Sandbox Code Playgroud)

由于您现在共享一个公共索引,因此您可以执行以下操作:

SELECT id, type, timestamp FROM table_common
WHERE client_id=1 ORDER BY timestamp LIMIT 100;
Run Code Online (Sandbox Code Playgroud)

如果您需要子表中的更多字段,请在条件中使用LEFT OUTER JOIN和包含type:

SELECT * FROM table_common
LEFT OUTER JOIN table_a ON table_common.type='a' AND table_common.id=table_a.id
LEFT OUTER JOIN table_b ON table_common.type='b' AND table_common.id=table_b.id
ORDER BY timestamp LIMIT 100;
Run Code Online (Sandbox Code Playgroud)