2012-04-26 3 views
0

UPDATE:日付/時刻フィールドをクエリーの日付フィールドに変更しているようです。mysql:RIGHT JOINのカレンダーテーブルに関するクエリースピードの問題

DATE(all_griefs_tbl.actioned_dateを使用すると、actioned_dateを日付フィールドに変更したり、日付と時刻フィールドに分割したりすることなく、より迅速な方法がありますか?

私が取得したい私は2つのテーブル、ステータスや日時フィールドを持つレコードの負荷を持つものを持っているし、他は2008から2015年

に日付とカレンダーのテーブルでは、すべての日付ですそのカウントがゼロであったとしても - - 期間と毎日「受け入れ」されたレコードの数に次のようになります。

| Date  | number_accepted | 
---------------------------- 
2012-03-01  723 
2012-03-02  723 
2012-03-03  1055 
2012-03-04  1069 
2012-03-05  0 
2012-03-06  615 
2012-03-07  0 
2012-03-08  1072 
2012-03-09  664 
2012-03-10  859 
2012-03-11  0 
2012-03-12  778 
2012-03-13  987 

私は次のことを試してみたが、それは速いだけです小さなデータサンプル(-1000行)で十分です。私は作品だけでなく上に少なくとも600K行

SELECT calendar.datefield AS Date, 
     COUNT(all_griefs_tbl.actioned_status) AS total_griefs 
FROM all_griefs_tbl 
RIGHT JOIN calendar 
    ON (DATE(all_griefs_tbl.actioned_date) = calendar.datefield) 
    AND all_griefs_tbl.actioned_status = 'accepted' 
WHERE calendar.datefield < CURDATE() 
GROUP BY calendar.datefield 

おかげ

ある何かを必要と

EDIT:ものの、

id select_type  table   type possible_keys  key    key_len  ref  rows Extra 
1 SIMPLE   calendar  range PRIMARY   PRIMARY   3   NULL 1576 Using where; Using index 
1 SIMPLE   all_griefs_tbl ref  actioned_status actioned_status 153   const 294975 
+0

実行計画(選択前に説明を追加するときの出力) –

+0

は、日付ごとにカレンダー表を提供してください。あなたは、現在の日付が何であれ、2008年以来毎日毎日行くのですか?毎回再計算するのではなく、1日あたりの集計を持つサマリー表を使用する方がよい場合があります。 – DRapp

+0

アイデアはハイスタンチャートのデータを入手することでした - http://www.highcharts.com/ 2008年から現在までは理想的でしょう。私は少なくとも1がある限り、1日あたりのカウントを得ることができます...私はこの仕事を得ることができない場合は、秋になると思います。 – eek

答えて

1

いくつかの考え...

ファーストを要求したとして、実行計画dbクエリで値が返されずに日が必要であると述べているので、実際に処理されている結果セットでこのチェックを行います。結合を行うたびに、クエリがはるかに複雑になり、処理に必要なメモリが増えます。この場合、私はカレンダーテーブルの使用をリレーショナルデータベースの特に有効な使用とみなしません。

編集:明確にするために、どのようにクエリが呼び出されていますか?つまり、開発中のプログラムがデータベースにアクセスし、クエリを実行して結果を表示していますか?もしそうなら、プレゼンテーションの前にこのプログラムを処理して結果を処理することをお勧めします。

第2に、あなたが 'join'にコミットしている場合、これはあなたが結合を行っているカラムであるので、all_griefs_tbl.actioned_dateに実際にインデックスを持つべきです。代わりに、calendar.datefieldに外部キーを指定することもできます。

第3に、機能DATE(all_griefs_tbl.actioned_date)を使用する必要がありますか?これはすでに日付ではないですか? (あなたのデータ型はわかりませんが、これとcalendar.datefieldが同じデータ型でない場合は、データベース設計が悪いように見えます)

EDIT:あなたの意見に照らして、all_griefs_tbl.actioned_dateを2つの列日付欄all_griefs_tbl.actioned_dateおよびタイムスタンプ欄all_griefs_tbl.actioned_timeを含む。現時点では、このすべての行にこのDATE()関数を実行して、結合を実行するにはall_griefs_tblを実行しています。これは非常に迅速にクエリを遅くします。これにより、の日付の時刻の両方にインデックスを追加することもできます(現在のdbデザインを考えれば、actioned_dateのインデックスは役に立ちませんでした)私は、DATE()関数のために、現在actioned_date列のインデックスでEXPLAINを再実行すると、all_griefs_tblにこのインデックスを使用しても表示されないことを期待しています。)

第4に、all_griefs_tbl.actioned_statusに格納されている情報の種類を検討することができます。これはブール値で置き換えられますか?これは、データの格納と処理の両方でより効率的になります。 (ただし、これはデータベースの設計によりますが)

編集:all_griefs_tbl.action_statusをより小さいデータ型に変更することを検討してください - 現在varcharと思われますが、これを単一の(または小さな)charデータ型に簡単に変更できます、またはさらに多くのブール値にまで及ぶ。しかし、これは主なパフォーマンスのオーバーヘッドではないと思っています。実際には、プロジェクトのニーズに応じてデータベース設計の意思決定がより複雑になります。

+0

返事をありがとう。私はカレンダーテーブルを使用しているので、ある期間内にすべての日付を取得するので、欠落しないようにします。もっと良い方法があれば、私はそれを聞いてみたいです。私は参加を約束していない、私はそれを行う別の方法を知らない。私はall_griefs_tbl.actioned_dateのインデックスを持っていましたが、あまり差をつけていないようです。 calendar.datefieldは日付フィールド、all_griefs_tbl.actioned_dateは日時フィールドです。それが唯一の違いです。 all_griefs_tbl.actioned_statusにはいくつかのステータスがあります:受け入れ、キュー、ロック – eek

+0

私はここで何が達成されようとしています:http://www.richnetapps.com/using-mysql-generate-daily-sales-レポートがいっぱい - ギャップ/違い私は値の集計ではなく、時間枠内の行の数を数えています。 – eek

+0

@eek - 私は私の答えに編集としてコメントを追加しました。 – amaidment

1

私は2つの別々の日付と時刻の列に日時からあなたactioned_dateを分割することをお勧め、あなたが

ON (all_griefs_tbl.actioned_date = calendar.datefield) 

と追加に

ON (DATE(all_griefs_tbl.actioned_date) = calendar.datefield) 

から、あなたの最初の結合条件を変更することができactioned_dateactioned_time言うことができますインデックス

ALTER TABLE all_griefs_tbl ADD INDEX g_status_date(actioned_status, actioned_date, actioned_time); 

これはおそらく、600k行のテーブルのクエリを瞬時に行うでしょう。

+0

それは私が思う一つの解決策ですが、私が知りたいのは、DATE()の代わりにもう一つのメソッドがあれば、それを使うことができます。 2つの別々の列に分割することは最後の手段になります。 – eek

+0

+1の分割提案の場合 – eek

+0

分割すると、上記のインデックスをグループbyにも使用できます。これは、秒単位ではなくmsec単位で話をすることに違いがあります。 – piotrm