2

次のようなテーブルがあります。

| calls | CREATE TABLE `calls` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `request_id` int(10) unsigned NOT NULL,
  `ct` int(10) unsigned DEFAULT NULL,
  `wt` int(10) unsigned DEFAULT NULL,
  `cpu` int(10) unsigned DEFAULT NULL,
  `mu` int(10) unsigned DEFAULT NULL,
  `pmu` int(10) unsigned DEFAULT NULL,
  `caller_id` int(10) unsigned DEFAULT NULL,
  `callee_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `caller_id` (`caller_id`,`request_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3164057 DEFAULT CHARSET=utf8 |

そして、単純なクエリは次のとおりです。

mysql> EXPLAIN SELECT
    -> AVG(`c1`.`wt`) `wt`,
    -> AVG(`c1`.`cpu`) `cpu`,
    -> AVG(`c1`.`mu`) `mu`,
    -> AVG(`c1`.`pmu`) `pmu`
    -> FROM
    -> `calls` `c1`;
+----+-------------+-------+------+---------------+------+---------+------+---------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------+
|  1 | SIMPLE      | c1    | ALL  | NULL          | NULL | NULL    | NULL | 3161147 |       |
+----+-------------+-------+------+---------------+------+---------+------+---------+-------+
1 row in set (0.00 sec)

mysql> SELECT
    -> AVG(`c1`.`wt`) `wt`,
    -> AVG(`c1`.`cpu`) `cpu`,
    -> AVG(`c1`.`mu`) `mu`,
    -> AVG(`c1`.`pmu`) `pmu`
    -> FROM
    -> `calls` `c1`;
+-----------+----------+------------+------------+
| wt        | cpu      | mu         | pmu        |
+-----------+----------+------------+------------+
| 2285.2079 | 428.2061 | 30567.4517 | 24925.7182 |
+-----------+----------+------------+------------+
1 row in set (1.61 sec)

サーバーはかなり高速です (24 GB の RAM)。my.cnf(完全な my.cnf )の中で最も関連性の高いものは次のとおりです。

query_cache_type=0
query_cache_size=0
key_buffer_size=50M
sort_buffer_size=10M
innodb_buffer_pool_size=1G
read_rnd_buffer_size=1M
join_buffer_size=4M
max_connections=400
table_cache=2000
table_definition_cache=2000

クエリを最適化するためにできることはありますか? 5,278,808 レコードしかないので、ハードウェアの限界に達したとは思えません。

また、テーブル全体を同じテーブルに移動しようとしましたENGINE=MEMORY。時間は約 30% 改善されました。ただし、それでも遅いです。

4

2 に答える 2

0

古いデータを何度も何度も見ないようにすることもできます...

おそらく、レコード数と合計値を最終更新日時とともに別のテーブルに保存し、日時列を呼び出しテーブルに追加します(インデックスが付けられていることを確認してください)。

平均を計算する必要がある場合は、最後にチェックした後に作成されたデータを見て、これを新しいテーブルのデータと組み合わせて、新しいテーブルを更新します。

古いデータを更新できる場合は、さらに複雑になります。その場合、おそらくトリガーが必要になるでしょう。

于 2012-09-19T22:34:14.050 に答える
0

あなたができる最善の短期的な方法は、計算する4つのフィールドをカバーするインデックスを追加することです. 現在、完全なテーブル スキャンを実行しています。MySQL の上の 4 列のみをカバーするインデックスを作成する場合、テーブルを含むすべてのページを対象とする操作は代わりにインデックスを対象とします。インデックスは個別に保存され、含まれるデータが少ないため、より多くのデータが 1 つのファイルに収まります。単一ページ。

于 2012-09-19T19:37:17.453 に答える