web-dev-qa-db-ja.com

MySQLでsum()を高速化することは可能ですか?

MySQLデータベースで「selectsum(foo)from bar」クエリを実行しています。これは、7.3mmレコードを合計し、実行ごとに約22秒かかります。 MySQLで合計を高速化するコツはありますか?

24
Teflon Ted

いいえ、関数自体を高速化することはできません。ここでの問題は、実際には730万レコードを選択していることです。 MySQLはテーブル全体をスキャンする必要があり、730万はかなり大きな数です。実はこんなに早く終わってしまったのが印象的です。

採用できる戦略は、データをより小さなサブセットに分割し(おそらく日付ごと、月ごと?)、変更されない古いデータの合計を維持することです。合計を定期的に更新することができ、合計と、それ以降に追加された新しいデータを追加することで全体の値を計算できます。これにより、行数が大幅に少なくなります。

36
zombat

MysqlでQUERYCACHEをオンにします。キャッシュはデフォルトでオフになっています。 mysqliniファイルを設定する必要があります。

-- hint mysql server about caching
SELECT SQL_CACHE sum(foo) FROM bar;

テーブルに変更が加えられていない場合、MySQLオプティマイザはキャッシュを返すことができる場合があります。

詳細はこちら: http://www.mysqlperformanceblog.com/2006/07/27/mysql-query-cache/

11
Yada

ここで2つのこと:

1)定期的に730万レコードの合計を行うべきではありません-ビジネスニーズ(日、月、年、部門など)に対応するステージングテーブルを導入し、スケジュールに基づいて入力します。元のテーブルの代わりにそれらのテーブルを再利用する可能性があります。 'テーブル(数日間隔が必要な場合の各日の要約値の選択など)

2)トランザクション設定を確認します

http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read

9

いいえ、そうではありません。テーブル内のすべての行を常に列挙する必要があります。

追加のテーブルを作成し、挿入、更新、削除のたびにその合計を更新できますか?

3
Phill

おそらくbar.fooフィールドにインデックスを追加してみることができます。インデックスにはbar列のすべての値が含まれますが、特にfooに他の列が多数ある場合は、元のfooテーブルよりも小さいためスキャンが高速になります。

1
hongliang

クエリが本当に単純な場合は、違います...しかし、より複雑なクエリを使用している場合(ここでは省略している場合)、(おそらく)-より良い結合を使用するように...

0
Gnark