同じレイアウトの複数のテーブルで構成されるロギングシステムをセットアップしただけです。
データソースごとに1つのテーブルがあります。
ログビューアについて、私はしたいです
- 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
条件のないクエリもあるでしょう。
テーブルはすでに存在し、データが入力されています。ソースによってはレイアウトが変更になる可能性があるので分割していきたいと思います。さらに、ログクライアントは、理由により異なる資格情報を使用します。
ログリーダーと実際のテーブルの間に一種のレイヤーを維持する必要があります。
以下は、クエリ全体と最初のサブクエリの実行プラン、およびテーブルレイアウトの詳細です。
UNION DISTINCT
?余分なID列があるため、結果はサブクエリ間で異なるため、強制的に並べ替えて区別する必要はありません。を使用しUNION ALL
ます。
source
ます。列を追加して、これらのすべてのログを同じテーブルに置く方が良いのではないでしょうか。このようにして、UNION
sを回避し、すべてのデータでインデックスを使用できます。
UNION ALL
別の実行プランが生成されるかどうかを確認します。
(account_id, zeitpunkt)
です。そのような指標はありますか?2番目に優れているのは(私は)シングルです(zeitpunkt)
が、それを使用した場合の効率は、行がaccount_id=730
表示される頻度に依存します。