2012-04-18 5 views
2

私は、両方とも時系列データを含んでいる2つの異なるMySQLテーブルを持っています(両方とも 'タイムスタンプ'カラムを含んでいます)。 'timestamp'カラムを除いて、2つのテーブルは 'client_id'カラム以外の共通の機能を共有しません。MySQL UNION LIMITsの性能

table_a 
- id 
- client_id 
- timestamp 
- ... 

table_b 
- id 
- client_id 
- timestamp 
- ... 

両方のテーブルのインデックスは(client_id、timestamp)です。

私はこれらの2つのテーブルを1つのページ設定された時系列に結合しようとしています。具体的には、これは、timestampで注文されたtable_atable_bの和集合からN個のレコード(Mのオフセットを持つ)をロードしようとしていることを意味します。

私はこのような文でこれを行うにしようとしました:

(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クエリを記述します。個々のテーブルに対するクエリ

注超高速ですか?定義により、あなたは個々のクエリのいずれかからN行以上のものを必要とすることはありませんので、これを行うには

答えて

5

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を使用して含まれている場合

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

簡単な方法としては、個々のクエリのそれぞれに同じ制限を適用することです:

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

この条件では、typeはf最初のページ、オフセットではありません。 –

+0

@FrancisAvila、良い点。私はその質問を十分に見ていませんでした。 –