0

私はテーブルを持っています

CREATE TABLE `symbol_details` (
  `symbol_header_id` int(11) DEFAULT NULL,
  `DATE` datetime DEFAULT NULL,
  `ADJ_NAV` double DEFAULT NULL
)

〜20,000,000エントリ。ここで、1つのsymbol_header_idについて、四半期の終わりに最も近いADJ_NAV値を見つけたいと思います。

SET @quarterend = '2009-3-31';

SELECT  symbol_header_id AS she, ADJ_NAV AS aend FROM symbol_details
WHERE
 symbol_header_id = 18546 
 AND DATE= (
# date closest after quarter end
SELECT DATE FROM symbol_details
WHERE ABS(DATEDIFF(DATE, @quarterend)) < 10
AND DATE<=@quarterend
AND symbol_header_id = 18546 
ORDER BY  ABS(DATEDIFF(DATE, @quarterend)) ASC LIMIT 1)

内部の「日付の選択」クエリを実行すると、すぐに返されます。サブクエリの代わりに正しい日付を入力して外部クエリを実行するだけでも、非常に迅速に終了します。しかし、私がすべてを実行すると、それは永遠にかかります-何かが間違っていますか?

4

3 に答える 3

2

オプティマイザーには、ステートメントを適切に評価し、最も効率的な計画を見つけるためのいくつかの問題があるようです。(Oracleでは、統計を更新するようにお願いしますが、MySQLでオプティマイザーがどのように機能するかはわかりません。)

オプティマイザーにとって何が最も理にかなっているのかを確認するために、ステートメントを表現する他の方法をいくつか試してみます。

  • イマーと外部クエリの2つのsymbol_header_idsを明示的に接続します
  • SELECT max(date) ..'Order ByLimit1'の代わりに試してください
  • symbol_detailsの自己結合を試してください

ここに役立つアイデアがあることを願っています。

于 2009-11-22T18:01:57.830 に答える
1

おそらくサブクエリなしで実行できます。最初の行を取得するだけです。

SELECT *
FROM symbol_details
WHERE DATE <= @quarterend
AND symbol_header_id = 18546
ORDER BY DATE DESC
LIMIT 1
于 2009-11-22T17:57:40.197 に答える
1

試す:

   SELECT t.symbol_header_id,
          COALESCE(t.adj_nav, '0.0') 'adj_nav'
     FROM SYMBOL_DETAILS t
LEFT JOIN (SELECT sh.symbol_header_id,
                  MAX(sh.date) 'max_date'
             FROM SYMBOL_DETAILS sh
            WHERE ABS(DATEDIFF(sh.date, @quarter_end)) < 10
              AND sh.date <= @quarter_end) x ON x.symbol_header_id = t.symbol_header_id
                                            AND x.max_date = t.date
   WHERE t.symbol_header_id = 18546
于 2009-11-22T18:25:22.907 に答える