4

両方に時系列データが含まれている 2 つの異なる MySQL テーブルがあります (どちらにも「タイムスタンプ」列が含まれています)。「timestamp」列を除いて、2 つのテーブルは「client_id」列以外に共通の機能を共有していません。

table_a
- id
- client_id
- timestamp
- ...

table_b
- id
- client_id
- timestamp
- ...

両方のテーブルは (client_id、タイムスタンプ) でインデックス化されます。

これらの 2 つのテーブルを単一のページ付けされた時系列に結合しようとしています。具体的に言うと、これは、table_aとの結合から N 個のレコード (オフセットは M) をロードしようとしていることを意味table_btimestampます。

私は次のようなステートメントでこれをやろうとしました:

(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

2 つの別個のテーブルに 2 つの別個のインデックスがあるため、ここではインデックスを十分に活用できません。

個々の選択ごとに制限を追加できますが、これは最初のページでのみ機能し、オフセットでは機能しません。

「ページ」に制限とオフセットを加えたものであるという要件を削除したい場合は、日ごとなど、他の絶対的な (相対的ではなく) 方法でページ付けすることができます。例えば:

(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 の共通属性が 3 番目のテーブルにある可能性もあります。このパターンを「結合テーブル継承」と呼びます。

例えば:

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

これを行う簡単な方法の 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 に答える