4

我有两个不同的 MySQL 表,它们都包含时间序列数据(其中都包含“时间戳”列)。除了“timestamp”列之外,这两个表除了“client_id”列之外没有任何共同的特征。

table_a
- id
- client_id
- timestamp
- ...

table_b
- id
- client_id
- timestamp
- ...

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

我正在尝试将这两个表组合成一个分页时间序列。具体来说,我的意思是我试图从 and 的table_a并集加载 N 条记录(偏移量为 M) table_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;

不幸的是,生成的查询似乎是从两个表中获取所有匹配的行,组合,然后应用 LIMIT。

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

SELECT 'a', id FROM table_a WHERE client_id=1 ORDER by timestamp LIMIT 100

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

4

2 回答 2

6

你不能在这里很好地利用索引,因为两个单独的表中有两个单独的索引。

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

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

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

但是,您的数据也可能未完全规范化,并且 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)
...

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

SELECT id, type, timestamp FROM table_common
WHERE client_id=1 ORDER BY timestamp LIMIT 100;

如果您需要子表中的更多字段,请使用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;
于 2012-04-18T16:33:20.770 回答
-1

一种简单的方法是对每个单独的查询应用相同的 LIMIT,因为根据定义,任何单独的查询都不需要超过 N 行:

(SELECT 'a', id FROM table_a WHERE client_id=1 ORDER BY timestamp LIMIT 100) 
UNION 
(SELECT 'b', id FROM table_b WHERE client_id=1 ORDER BY timestamp LIMIT 100) 
ORDER BY timestamp 
LIMIT 100;
于 2012-04-18T16:13:27.973 回答