2

次のSQLコードがあります。

select val.PersonNo,
       val.event_time,
       clg.number_dialed
  from vicidial_agent_log val
         join
       call_log           clg on date_add('1970-01-01 02:00:00', interval clg.uniqueid second) = val.event_time
 order by val.event_time desc
 limit 100;

これは、1 秒未満で行を実行して返します。ただし、ストレート結合を a に変更するとleft outer:

select val.PersonNo,
       val.event_time,
       clg.number_dialed
  from vicidial_agent_log val
         left outer join
       call_log           clg on date_add('1970-01-01 02:00:00', interval clg.uniqueid second) = val.event_time
 order by val.event_time desc
 limit 100;

クエリは永遠に実行され、サーバーの CPU の ~100% を使用します。

私は両方のクエリを実行しましたが、最初のクエリは のインデックスにexplainヒットし、2 番目のクエリはすべてのインデックスを無視しました。に索引があります。event_timevicidial_agent_logcall_log.uniqueid

vicidial_agent_log~41,000 行をcall_log含み、 ~43,000 行を含みます。

だから私の質問は - MySQL が私が定義したインデックスにヒットしないのはなぜですか、強制的にそうさせる方法はありますか? そうでない場合、どうすればこのクエリを許容できる速度で実行できますか?

編集

完全なソリューション:

select val.PersonNo,
       val.event_time,
       cl.number_dialed
  from vicidial_agent_log val
         left outer join
       (select date_add('1970-01-01 02:00:00', interval clg.uniqueid second) as 'converted_date',
               number_dialed
          from call_log clg) cl ON cl.converted_date = val.event_time
 order by val.event_time desc
 limit 100;
4

5 に答える 5

3

を使用するLEFT JOINと、LEFT表は常に に進みMySQLます。

最初のクエリでMySQLは、先頭にするテーブルを選択でき、選択したclg.

現在は選択できず、この条件:date_add('1970-01-01 02:00:00', interval clg.uniqueid second)はサージ可能ではありません。

の値を見つけるために使用できるインデックスはありませdate_add('1970-01-01 02:00:00', interval clg.uniqueid second)ん。MySQLval.event_time

クエリを次のように書き換えます。

SELECT  val.PersonNo,
        val.event_time,
        clg.number_dialed
FROM    vicidial_agent_log val
LEFT OUTER JOIN
        call_log clg
ON      clg.uniqueid = UNIX_TIMESTAMP(val.event_time) - 7200
ORDER BY
        val.event_time desc
LIMIT 100
于 2009-08-26T16:22:41.913 に答える
1

一致するすべてのレコードを含める必要があり、一致しないレコードにはnullを提供する必要があるため、外部結合がテーブルスキャンを強制していると思います。

mck89のソリューションは非常にうまく機能する可能性がありますが、使用する理由はありませんでした...これがどうなるか興味があります。

于 2009-08-26T16:13:04.850 に答える
1

最初はインデックスを使用できます。これは、内部結合では、インデックスの基になっている列(Event_Time)の値に基づいて結合の結果セットをフィルタリングしているためです...

外部結合を使用している2番目のクエリでは、出力をフィルタリングしていないため、event_timeの値に関係なく、結果セットにすべてのレコードを含める必要があるため、全表スキャンを実行する必要があります...

于 2009-08-26T16:16:55.670 に答える
1

JOIN または WHERE 句で関数を使用すると、常にインデックスに混乱が生じます。例:

DATE_ADD('1970-01-01 02:00:00', INTERVAL clg.uniqueid SECOND)

データベースは、あなたの場合の event_time 列との比較ではなく、変換の値を検索するために uniqueid インデックスを使用しています。これが PLW エラーがオンになっている Oracle である場合は、データ型から変換される可能性があることが通知されます。

このような状況は常に比較の前に処理する必要があります。つまり、インライン ビューを使用して変換を実行し、その結果列に結合します。いいえ:

JOIN (SELECT DATE_ADD('1970-01-01 02:00:00', INTERVAL clg.uniqueid SECOND) 'converted_date'
        FROM CALL_LOG clg) cl ON cl.converted_date = val.event_time
于 2009-08-26T16:19:17.460 に答える
-1

FORCEINDEXを使用できます

于 2009-08-26T16:09:31.753 に答える