5

約 50 ミリ秒で 3744 行を生成するこの複雑なクエリがあります。

 SELECT 
  srl.event_id as eid
 , srl.race_num as rnum
 , bts.boat_id as bid_id
 , srl.series_year as yr
 , srl.id as id 
 , IFNULL(rfi.fleet,fleet_def) as flt_old,flt_match,s.series_id as sid
 , s.series_year as syr
  ,IFNULL(ovr_pts,POINTS('4',IFNULL(ovr_place,place),num_start)) as points

 FROM

 (SELECT en1.boat_id,en1.boat_name,MAX(fleet) as fleet_def FROM entries en1 
 JOIN series_race_list srl1 ON srl1.event_id=en1.event_id 
              AND srl1.series_year=en1.race_year 
 LEFT JOIN entries_race er1 ON en1.boat_id= er1.boat_id 
                           AND srl1.event_id=en1.event_id      
                           AND srl1.series_year =en1.race_year 
 WHERE srl1.series_id ='3' AND srl1.series_year ='2012' 
                            AND en1.entry_deleted='N'      
 GROUP BY boat_id) bts 

 JOIN series_race_list srl LEFT JOIN series as s ON s.series_id=srl.series_id 
 AND s.series_year =srl.series_year 

 LEFT JOIN entries as en ON srl.event_id=en.event_id 
  AND srl.series_year =en.race_year AND bts.boat_id =en.boat_id 

 LEFT JOIN entries_race er ON er.race_id= srl.event_id AND er.race_num=srl.race_num 
                        AND er.yr = srl.series_year AND bts.boat_id =er.boat_id

 LEFT JOIN event_race_info as eri ON eri.race_id= srl.event_id 
     AND eri.race_num=srl.race_num AND eri.yr = srl.series_year 
     ANd er.line=eri.line     AND status REGEXP 'prelim|final' 

 LEFT JOIN race_results as rr ON srl.event_id=rr.race_id 
     AND srl.race_num= rr.race_num   AND srl.series_year =rr.yr 
     AND bts.boat_id= rr.boat_id AND checked_in='Y' 

LEFT JOIN race_fleet_info as rfi ON rfi.race_id= srl.event_id 
     AND rfi.yr=srl.series_year AND srl.race_num= rfi.race_num 
     AND rfi.fleet=rr.flt AND complete='Y'

LEFT JOIN series_pts_override as spo ON srl.id =spo.id AND en.boat_id =spo.bid

WHERE s.series_id ='3' AND s.series_year ='2012' AND approved ='Y'

長々とすみません。前述のとおり、このクエリは約 50 ミリ秒で実行されます。ここで、このデータを使用して、この 3744 行の結果に対してクエリを実行したいと考えています。これを次のようなクエリでラップするとすぐに

SELECT eid FROM(
     ......previous query here.....
         ) data

実行時間が 50 ミリ秒から 2.5 秒に短縮されました。

一時テーブルを作成してみましたが、同じでした。(実際には、この結果セットに対していくつかの異なるクエリを実行する必要があるため、これが私の好みのアプローチです。

このサイトを読むと、これは相関サブクエリではないと思いますが、相関サブクエリのように動作しているようです。

サブクエリには派生テーブルのエイリアスがあり、一時テーブルは明らかにテーブルであるため、エイリアステーブルを作成する行為が私の問題であるようです。

この時間のペナルティなしで、これらの 3744 行のデータにアクセスするにはどうすればよいですか?

それが役立つ場合は、説明を投稿する方法を理解できます。

長いクエリについて説明します。

id      select_type   table       type    possible_keys               key        key_len  ref                                                   rows    Extra
1       PRIMARY       <derived2>  ALL     NULL                        NULL       NULL     NULL                                                  3744
2       DERIVED       s           const   PRIMARY                     PRIMARY    5                                                              1
2       DERIVED       srl         ref     series_id,series_id_2       series_id  5                                                              16      Using where
2       DERIVED       <derived3>  ALL     NULL                        NULL       NULL     NULL                                                  208     Using join buffer
2       DERIVED       en          eq_ref  PRIMARY,event_id,event_id_2 PRIMARY    9        race_reg_test.srl.event_id,bts.boat_id                1       Using index
2       DERIVED       er          ref     PRIMARY,boat_id,boat_id_2   boat_id_2  5        bts.boat_id                                           5
2       DERIVED       eri         eq_ref  PRIMARY                     PRIMARY    13       race_reg_test.srl.event_id,race_reg_test.srl.race_... 1
2       DERIVED       rr          ref     PRIMARY,boat_id             boat_id    4        bts.boat_id                                           9
2       DERIVED       rfi         eq_ref  PRIMARY                     PRIMARY    31       race_reg_test.srl.event_id,race_reg_test.srl.race_... 1
2       DERIVED       spo         ref     PRIMARY                     PRIMARY    8        race_reg_test.srl.id,race_reg_test.en.boat_id         1
3       DERIVED       srl1        ref     series_id,series_id_2       series_id  5                                                              16      Using index; Using temporary; Using filesort
3       DERIVED       en1         ref     PRIMARY,event_id,event_id_2 PRIMARY    5        race_reg_test.srl1.event_id                           11      Using where
3       DERIVED       er1         ref     boat_id,boat_id_2           boat_id    4        race_reg_test.en1.boat_id                             9       Using index
4

2 に答える 2

0

あなたは一時テーブルを作成しようとしたと言いましたが、それがビューを意味するかどうかはわかりません。

そのクエリでビューを作成し、ビューで必要なクエリを実行します。

CREATE VIEW massive_query_view AS 
SELECT 
  srl.event_id as eid
 , srl.race_num as rnum
 , bts.boat_id as bid_id
 , srl.series_year as yr
 , srl.id as id 
 , IFNULL(rfi.fleet,fleet_def) as flt_old,flt_match,s.series_id as sid
 , s.series_year as syr
  ,IFNULL(ovr_pts,POINTS('4',IFNULL(ovr_place,place),num_start)) as points

 FROM

 (SELECT en1.boat_id,en1.boat_name,MAX(fleet) as fleet_def FROM entries en1 
 JOIN series_race_list srl1 ON srl1.event_id=en1.event_id 
              AND srl1.series_year=en1.race_year 
 LEFT JOIN entries_race er1 ON en1.boat_id= er1.boat_id 
                           AND srl1.event_id=en1.event_id      
                           AND srl1.series_year =en1.race_year 
 WHERE srl1.series_id ='3' AND srl1.series_year ='2012' 
                            AND en1.entry_deleted='N'      
 GROUP BY boat_id) bts 

 JOIN series_race_list srl LEFT JOIN series as s ON s.series_id=srl.series_id 
 AND s.series_year =srl.series_year 

 LEFT JOIN entries as en ON srl.event_id=en.event_id 
  AND srl.series_year =en.race_year AND bts.boat_id =en.boat_id 

 LEFT JOIN entries_race er ON er.race_id= srl.event_id AND er.race_num=srl.race_num 
                        AND er.yr = srl.series_year AND bts.boat_id =er.boat_id

 LEFT JOIN event_race_info as eri ON eri.race_id= srl.event_id 
     AND eri.race_num=srl.race_num AND eri.yr = srl.series_year 
     ANd er.line=eri.line     AND status REGEXP 'prelim|final' 

 LEFT JOIN race_results as rr ON srl.event_id=rr.race_id 
     AND srl.race_num= rr.race_num   AND srl.series_year =rr.yr 
     AND bts.boat_id= rr.boat_id AND checked_in='Y' 

LEFT JOIN race_fleet_info as rfi ON rfi.race_id= srl.event_id 
     AND rfi.yr=srl.series_year AND srl.race_num= rfi.race_num 
     AND rfi.fleet=rr.flt AND complete='Y'

LEFT JOIN series_pts_override as spo ON srl.id =spo.id AND en.boat_id =spo.bid

WHERE s.series_id ='3' AND s.series_year ='2012' AND approved ='Y'

次に、ビューでクエリを実行できます。

SELECT * FROM massive_query_view;

物事がスピードアップすることを願っています。他にできることは、インデックスを確認することです。インデックスを使用すると、where 句は高速になりますが、挿入は遅くなります。詳細については、MySQL がインデックスを使用する方法に関する MySQL ドキュメントを参照してください: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

于 2013-01-03T18:52:00.620 に答える
0

いくつかのことですが、私が見る最大のものはあなたの元のクエリにあります...

boat_id) bts JOIN series_race_list srl LEFT JOIN series as s

bts と srl の間に "ON" 条件がないため、デカルトの結果になり、おそらくあなたにとって大きな問題になります。bts のすべてのレコードに対して、srl でエントリを作成し、その製品からシリーズに参加します。明らかに有効な基準/キーで結合されているため、srl からシリーズまでは問題ありません。

次に、"bts" にエイリアスされる最も内側のクエリの max(fleet) など、alias.field ではないフィールドがいくつかあります。さらに、私が主キーとして解釈し、一意になるボート ID でグループ化されている場合、なぜ MAX(フリート) です... ボートはフリートを変更するのでしょうか? もしそうなら、これは正確ですか?フリートのテーブル (独自の自動シーケンス ID も持っている) があり、ボートが所有権/スポンサーシップ (何でも) を既存のフリートに変更した場合、例えば... フリート 93 から、既に ID を持っている新しいものに変更します。 47 のファイルでは、47 は最新の関係でしたが、古い既存の ID でした...それはあなたが本当に望んでいるものですか? MAX()?

alias.field がない場合の追加フィールド: ovr_pts および ovr_place、フィールド リストに配置 (および POINTS() 関数とは...status正規表現で配置、レース結果でchecked_in、レース フリート情報で完了、最終的に承認済み)最後の where 句マイナーですが、インデックスの最適化に役立つ可能性があります。

最後に、クエリには特定の "s.series_id... and s.series_year..." に対する WHERE 句がありますが、クエリの前半に LEFT-JOIN があります。これは基本的にその左結合コンポーネントをキャンセルし、有効な包含オプションとして NULL を許可していないため、暗黙の INNER JOIN に変換します。

いくつかの明確化の後、いくつかのクエリを変更することを提案することさえありますが、私が目にする最大のものは最初からでした... btsとseries_rate_listテーブルを結合する「ON」条件はありません。

于 2013-02-05T03:06:09.790 に答える