MySQLは非常に単純なSELECTクエリで非常に遅い


10

InnoDBエンジンを備えたMySQL 5.5データベースにデータを保存する仮想マシンで実行されている単純なWebアプリケーションがあります。約3年間はすべて問題なく動作しましたが、突然、非常に遅くなりました。

たとえば、住所を保持する非常に単純なテーブルがあります。

CREATE TABLE `addresses` (
  `address_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET latin1 NOT NULL,
  `firstname` varchar(64) CHARACTER SET latin1 NOT NULL,
  `street` varchar(64) CHARACTER SET latin1 NOT NULL,
  `housenumber` varchar(16) CHARACTER SET latin1 NOT NULL,
  `zip` varchar(5) CHARACTER SET latin1 NOT NULL,
  `city` varchar(64) CHARACTER SET latin1 NOT NULL,
  `email` varchar(64) CHARACTER SET latin1 NOT NULL,
  `phone` varchar(16) CHARACTER SET latin1 NOT NULL,
  `birthdate` date NOT NULL,
  PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

このテーブルには約800のエントリがありますが、実際にはそれほど多くありません。しかし、クエリを実行する

SELECT * FROM addresses

テスト目的のため、終了しないようです。私はこれをサーバー自体のmysql CLIで確認しました。テーブルのいくつかの行を出力し、次の行を出力するまで非常に長く待機します。

データ送信フェーズの問題かもしれませんが、よくわかりません。

VMには2GBのRAMがあり、320MBのみが使用されます。CPUも非常に低い1〜2%で実行されます。mytopには、サーバーをブロックしている他のクエリは表示されません。IT管​​理者は、ハードウェア側では何も変更しなかったと述べています。

データベースサーバーを再起動したり、仮想マシンを再起動したりするようなことはすでに試しました。何も役に立たなかった。

編集:

EXPLAIN SELECT * FROM addresses

私にこの結果を与えます:

+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | addresses | ALL  | NULL          | NULL | NULL    | NULL |  793 |       |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

Virtual Box、Xen、または他の何か?ホストディスクはどのように設定されていますか?同じボックスに他のVMも遅いのですか?それらの質問に答えると答えが明らかになるかもしれません
Matt

私はハイパーバイザーの所有者ではないので、これには答えられません。ハイパーバイザーの管理者に最近の変更を知っているかどうか尋ねましたが、彼は「いいえ」と答えました。
Tab

可能であれば、mysqlをシャットダウンして、ディスクとメモリのベンチマークを実行します。複雑である必要はありません。アイデアは、それがmysqlの問題であるか、おそらく以下の回答で示されているインデックスの問題であるか、より広範囲にあるかを特定することです。
マット

良い点は、おそらくmysqlの問題ではないということです。実行するmysql -u username -ppassword mydb -e 'SELECT * FROM addressesと出力が遅くなりますが、 `> test.txt`を追加すると、非常に速く実行されます。これはおそらく別の質問でしょう!?どうすればこれを調査できますか?
Tab

ハイパーバイザーの所有者に連絡し、エラーがないかログを確認するよう依頼してください。特にディスクエラー。彼にあなたの症状を教えてください。今すぐバックアップ。
Matt

回答:


13

CPUの負荷が低い場合は、インデックスが不足しているという問題がないことを示しています。その場合、クエリはCPUとディスクへのアクセスを増やす必要があるだけです。また、3年間は問題なく動作したとおっしゃっていました。

一般的なディスクアクセス速度(特にデータベースが配置されているパーティション)を確認しましたか?たとえばdd 、ここのように使用します。あなたが説明しているものは、死んだディスクや半死んだレイドのような音です。私が望むバックアップを得ましたか?


それは良い点です。これは、ホストのディスクエラーのように単純な場合もあります。
Matt

9

いくつかのことを試すことができます

  1. インデックスを設定していますか?

インデックスを作成すると、最初に全テーブルスキャンを行わなくてもレコードをすばやく見つけることができ、実行時間が大幅に短縮されます。

CREATE INDEX idx_name ON addresses(name);
  1. クエリを実行する前に、最初にEXPLAINキーワードを使用します。

SELECTクエリの前で使用すると、MySQLがクエリを実行する方法と、完了する前に処理する必要のある行数が記述されます。

  1. VMがRAMを増やす場合はmysql.iniに変更を加え、mysql.iniを構成してパフォーマンスが向上するかどうかを確認します。

あなたを導くことができる多くのMySQLオプティマイザがあります。

これが役立つ


わかりましたが、非常に小さなテーブル(<800行)にインデックスを作成することは、私が必要とするほど役に立ちません。上記のクエリを完了するには1分以上かかります。このような小さなテーブルのフルテーブルスキャンは、それほど長くはかかりません。
Tab

それで...インデックスを追加しましたか?あなたが問題が何であるかわからない場合は、私は基本的なものから始めて、自分の道を下ります。インデックスを追加しても、正しく実行した場合にのみパフォーマンスが向上します。
Anthony Fornito 2016年

はい、名前の列にインデックスを追加しました。しかし、上記のクエリには制限付きのWHERE句もないため、テーブル全体を読み取って出力する必要があります。追加されたインデックスは役に立たなかった。
タブ2016年

上記のEXPLAINクエリの結果を追加しました。これは私には問題なく見えますが、パフォーマンスはまだ非常に低いです。私は仮想化マネージャーの管理者ではないため、RAMを増やすことができません。しかしhtop、2050MBのRAMのうち307MBしか使用されていないことを示しています。
タブ

インデックスについては、インデックスを作成する列について本当に考える必要があります。すべてをインデックスに登録するのではなく、最大量のインデックスを作成する必要はありません。これについては、いくつかのワイルドな仮定を行っていますがname、「firstname」から始め ます。第二に、あなたは正しく索引付けをしたと確信していますか?possible_keys:NULL列がNULLの場合、関連するインデックスが見つからなかったことを示します。
Anthony Fornito 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.