mysqlがデータ送信に時間がかかりすぎる


9

数百万レコード(14,000,000)の単純なテーブルがあり、単純なクエリでは「データの送信」に時間がかかりすぎています。

テーブル

CREATE TABLE IF NOT EXISTS details (
  id int(11) NOT NULL,
  date date NOT NULL,
  time int(2) NOT NULL,
  minutes_online decimal(5,0) NOT NULL,
  minutes_playing decimal(5,0) NOT NULL,
  minutes_chatting decimal(5,0) NOT NULL,
  minutes_away decimal(5,0) NOT NULL
  PRIMARY KEY (id,date,time)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

簡単なクエリ

mysql> SELECT * FROM details WHERE id = 3014595;

説明する

mysql> EXPLAIN SELECT * FROM details WHERE id = 3014595;
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table     | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | details   | ref  | PRIMARY       | PRIMARY | 4       | const | 1482 |       |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+

クエリのプロファイル

mysql> SHOW PROFILE FOR QUERY 1;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000024 |
| checking query cache for query | 0.000078 |
| checking permissions           | 0.000014 |
| Opening tables                 | 0.000126 |
| System lock                    | 0.000011 |
| Table lock                     | 0.000030 |
| init                           | 0.000027 |
| optimizing                     | 0.000117 |
| statistics                     | 0.040077 |
| preparing                      | 0.000029 |
| executing                      | 0.000006 |
| Sending data                   | 7.536960 |
| end                            | 0.000013 |
| query end                      | 0.000004 |
| freeing items                  | 0.000037 |
| storing result in query cache  | 0.000006 |
| logging slow query             | 0.000003 |
| cleaning up                    | 0.000006 |
+--------------------------------+----------+

ご覧のとおり、SELECTステートメントはインデックスを使用し、1482行のみを読み取りました。それでも、クエリは7.536960秒かけてデータを送信しました。これは、クエリが必要とするより多くの行を読み取るようです。

これは単純なクエリで、わずか7フィールド(行平均59バイト)であり、ファンシー関数はありません。これを引き起こしている可能性のあるアイデアはありますか?

注:idはユーザーIDです。各ユーザーは、毎日の1時間ごとに少なくとも1つのエントリを持つことができます。したがって、IDは一意ではありません。

編集:同じ構造とはるかに多くの行(3400万)を持つ別のテーブルがあります。この大きなテーブルで同じクエリを実行すると、1秒未満で結果が返されます。

唯一の違いは、大きいテーブルは小さいテーブルほど多くのクエリを取得しないことです。

  • クエリの数がプロセスを遅くしている可能性はありますか?MySQLキャッシュはオンです。また、CakePHPはクエリの数を減らすためにクエリをキャッシュします。
  • テーブルが保存されているファイルが破損しているなどの可能性はありますか?

アップデート この問題は、データ層をWeb層から分離することで解決されました。データ層もRAMがアップグレードされ、raid10で実行されています。


何行SELECT戻りますか?
hjpotter92

1591 rows in set (16.48 sec)もう一度クエリを実行しました。これが、期間が異なる理由です。今から16秒かかりました(!!)
rlcabral

*を使用する代わりに、列を使用してその違いを確認してください
Muhammad Raheel

いいえ。同じ結果。
rlcabral 2012

ID列を単純なプライマリインデックスにするようにしてください。IDは一意のフィールドでなければならないため、IDを使用して複雑なインデックスを作成する必要はありません。これにより、主キーによる検索が光速のように高速になります。
Alexander Pravdin 2017年

回答:


1

この質問に出くわして、RAMをアップグレードしなくても、データの送信にそれほど時間がかかったのではないかと疑問に思っている人は誰でも、実際に送信するデータには、送信するデータを検索する時間が含まれているからです。

https://dev.mysql.com/doc/refman/5.7/en/general-thread-states.html

スレッドはSELECTステートメントの行を読み取って処理し、データをクライアントに送信しています。この状態の間に発生する操作は、大量のディスクアクセス(読み取り)を実行する傾向があるため、多くの場合、特定のクエリの存続期間で最も長く実行される状態です。


-2

Optimize table tablenameを使用してテーブルを最適化し、ステータスを確認してください。

大きな変更を行う必要があります:

Alter table tablename engine = 'INNODB'

これは非常に役立ち、テーブルに1つの主キーがあるはずですが、主キーとして3つの列を追加しました。


-3

idに個別のインデックスを作成します。

テーブルの詳細を変更して、キーd1(id)を追加します。

このインデックスを有効にするには、MySQLを再起動するか、

テーブルの詳細を分析します。

可能であれば、トランザクションサポートやその他のメリットを得るために、データベースをInnoDBに変更することもできます。


これはどのように役立ちますか?
Colin 't Hart
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.