これは非常に基本的な質問のように思えますが、似たような質問がたくさんありますが、何時間もの調査と試行錯誤の末、答えが見つかりません。これが繰り返される場合は、お詫び申し上げます。
次の 2 つの条件に基づいて、テーブルに参加したいと考えています。
column_1 = something_1 AND column_2 = max(something_2 未満のすべての可能なエントリ)。
私はこれを行うことができるはずだと思います:
Select t1.id, t2.id from table1 as t1
join
(select t1.id, max(t2.condition_2) as big_condition_2 from table1 as t1
join table2 as t2
on t2.condition_1 = t1.condition_1 and t2.condition_2 < t1.condition_2
group by t1.id) as t3
on t3.id = t1.id
join table2 t2
on t2.condition_1 = t1.condition_1 and t2.condition_2 = t3.big_condition_2
このクエリは現在 20 分後にタイムアウトになっており、タイムアウトを削除するのにどれくらいの時間がかかるかわかりません。私はそれが何か間違っていると確信しています。
各テーブルには平均で約 100 のタイプがcondition_1
あり、各条件には約 4000 の異なるcondition_2
値があります。したがって、各テーブルには 300k から 500k の行があります。その場合、サブクエリは約 2000 x 100 = 200k の結合を生成する必要があると見積もっていますが、これは無駄ですが、それほど長い遅延が発生するとは思いません。condition_1
であり、int
でcondition_2
あることに注意してくださいvarchar(21)
。
必要に応じて個別にまたは複数の参照フィールドのそれぞれにインデックスがありますが、t3 への結合ではインデックスが使用されないため、この t3 テーブルを生成したという事実により、処理が大幅に遅くなる可能性があります。
もっと基本的には、私が知りたいのは、これらの不要な結合をすべて実行せずに、結合する特定の値を選択できる方法があるかどうかです。つまり、(疑似コード)のようなことをします:
select t1.id, t2.id from table1 as t1
join table2 as t2
on t2.condition_1 = t1.condition_1
and t2.condition_2 = max(t2.condition_2 where t2.condition_2 > t1.condition_1)
よろしくお願いします。
アップデート
スティーブのリクエストで、クエリの説明を実行しようとしましたが、20 分後にタイムアウトになりました。次に、サブクエリ部分だけで説明を実行しようとしたところ、次の出力が得られました
UPDATE 2いくつかの新しいインデックスを追加し、サブクエリで Explain を再実行しました。結果は次のとおりです (より読みやすいように書式設定されています)。
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE esnap index ticker_id,ticker_id_2,date_time_GMT PRIMARY 4 null 20
1 SIMPLE ep ref primary_ticker_id,secondary_ticker_id secondary_ticker_id 5 adr.esnap.ticker_id 1 Using where
1 SIMPLE ets ref ticker_id,date_time_GMT ticker_id 5 adr.ep.primary_ticker_id 22430 Using where; Using index
説明としてesnap
はtableA
、テーブルAとテーブルBを結合するために必要な中間テーブルであるテーブルですets
。したがって、サブクエリは実際には次のとおりです。tableB
ep
select esnap.security_snap_id, max(ets.date_time_GMT) as snap_time from
equity_snapshots esnap
join equity_pairs ep on ep.secondary_ticker_id = esnap.ticker_id
join equity_trade_snaps ets on ets.ticker_id = ep.primary_ticker_id and
ets.date_time_GMT < esnap.date_time_GMT
group by esnap.security_snap_id
ここで、ticker_id
はでint
、date_time_GMT
はvarchar(21)
です。
不可能なことを尋ねる?
さらに検討すると、サブクエリによって生成されるテーブルが大きすぎると思います。一致するペアはおよそ 100 あります ( condition_1
)。各ペアには、tableA に約 6500 の異なる ID があり、tableB に 3500 の異なる ID があります。これは、グループ化の前に、約 100 * 6500 * (3500/2) = 11 億行が結合されることを意味します。
ジャワに頼る...
他の誰かがサブクエリを回避する方法を提案できない限り (つまり、「ALL less than, then group」ではなく、「max less than」にのみ結合する)、私はあきらめて Java を使用して全体をインポートするつもりだと思いますテーブル、そのことを行い、結果を mySql に出力します。これはすべて、もっと単純にする必要があるものには非常に時間がかかるようです....だから、誰かがより良い解決策を持っているなら、私に知らせてください.