2009-05-14 20 views
24

MySQL 5.0.45に関する私のクエリの1つが、「データ送信」フェーズで遅く実行されています。問合せは単純な選択であり、結果セットとして約300の整数IDフィールドを戻します。MySql - データ送信フェーズを遅くする

 
mysql> SELECT source_id FROM directions WHERE (destination_id = 10); 
+-----------+ 
| source_id | 
+-----------+ 
|   2 | 
|   8 | 
... 
|  2563 | 
+-----------+ 
341 rows in set (2.13 sec) 

"データを送信する"フェーズが遅い理由と、それを速くするために何ができるのかが分かります。私はこのクエリをサーバ自体のMySQLプロンプトで実行しているので、実際には "データを送信"するのに非常に多くの時間を費やすとは思っていません。すべての手がかりは?

私はこのテーブルに3つのテキストフィールドを持っていますが、選択されていないため、この遅さが原因ではないと予想しています。

このクエリは1日に何千回も実行され、毎回2秒かかることはありません。

 
mysql> show profile for query 4; 
+--------------------------------+----------+ 
| Status       | Duration | 
+--------------------------------+----------+ 
| (initialization)    | 0.000003 | 
| checking query cache for query | 0.000051 | 
| checking permissions   | 0.000007 | 
| Opening tables     | 0.000011 | 
| System lock     | 0.000005 | 
| Table lock      | 0.000023 | 
| init       | 0.00002 | 
| optimizing      | 0.00001 | 
| statistics      | 0.00006 | 
| preparing      | 0.000014 | 
| executing      | 0.000005 | 
| Sending data     | 2.127019 | 
| end       | 0.000015 | 
| query end      | 0.000004 | 
| storing result in query cache | 0.000039 | 
| freeing items     | 0.000011 | 
| closing tables     | 0.000007 | 
| logging slow query    | 0.000047 | 
+--------------------------------+----------+ 
18 rows in set (0.00 sec) 

UPDATE:結果をプロファイリング

は、私は誰かが検証することができます

 
Each time means the time elapsed between the previous event and the new event. So, the line: 
| Sending data | 0.00016800 | 
means that 0.00016800 seconds elapsed between "executing" and "Sending data". It is, it takes 0.00016800 seconds to execute the query. 

http://forums.mysql.com/read.php?24,241461,242012#msg-242012

言い、次のURLにつまずきましたか?

+7

文は、リンク先のページには真実ではありません。クエリの実行中に 'SHOW PROCESSLIST'を実行すると、クエリが実際に**送信データ**の状態であることが示されます。 (前のものではない)。 - そして、プロセスリストが実行中の*次のステップを示していることは誰も言わないでください。 :) – vbence

+0

@vbence:実行するには少数の人がかかるクエリを見たことがありますか?上記の理論は理にかなっています。 –

+0

@ user9111337ああはい。集計文(GROUP BY)とWHERE caluseを使用すると、通常は索引を使用して解決できない選択が行われます(EXPLAIN ...は「USING WHERE」と表示されます)。表が十分に大きければ、数分かかることがあります。 - これはどのように報告されますか? 'SHOW PROCESSLIST'を試してみてください。 – vbence

答えて

1

このテーブルにインデックスがありますか?あなたはそれが約300を返すと言いました。しかし、それらの300を見つけるために何回検索する必要がありますか?

15

通常、説明が遅いクエリがある場合は常に、説明プランを開始するのが最適です。取得するには

DESCRIBE SELECT source_id FROM directions WHERE (destination_id = 10); 

これは、クエリを実行するために必要な手順を一覧表示するテーブルです。 「行」列に大きな値が表示され、「キー」列にNULLが表示された場合は、クエリが多数の行をスキャンして返すものを判断する必要があることを示します。

この場合、destination_idにインデックスを追加すると、インデックスを更新する必要があるため、速度を挿入したり削除したりするコストがかかります。

+10

私はEXPLAIN/DESCRIBEクエリが検索する方法に同意しますがそれを修正する方法を説明するには、「送信データ」フェーズが何であるかを実際には説明していませんでした。 http://dev.mysql.com/doc/refman/5.0/en/general-thread-states.html –

-2

あなたの質問は2.127019からまでです。クエリはです。これはおそらく大量のデータがあり、destination_id列にインデックスがないためです。試してください:

CREATE INDEX index_destination_idオン方向(destination_id);

あなたのリクエストはスムーズに実行されます。

+3

を参照してください。この文は偽です。質問に対する私のコメントを参照してください。 – vbence

+0

しかし私にとっては、別のシナリオでは、実際にインデックスを追加することで低速なクエリが解決されました。 –

6

おそらくmysqlサーバのハードウェア部分を見ることができます。 Mysql docとして は言う:

送信データ

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

だから、

、サーバーが原因tableperfileのInnoDBのオプション/フラグメンテーション/間違って設定RAID /ディスククラッシュ・プロセスは、(すぐにディスク死を待つ)を開始巨大なDB /テーブルファイルまたは無効に低速なディスクI/Oを持っている場合/他ディスクのI/O速度が遅い理由 - になります。この段階では、サーバーから要求されたすべてのデータを収集してクライアントに送信するように、「送信データ」ステップが大幅に増加しました。

もちろん、索引を最初に使用するようにselectを最適化して、これがプログラミングの問題ではないことを確認してください。これは、ほとんどの場合このステージ時間に影響します。

0

私は同じ問題を持っていた: は、データの送信が非常に遅かったが、私はあまり周りに掘った後など

を正しいインデックスを持っていた、私は私のjoinがインデックスされた2つのフィールドを比較していることがわかったが、異なっていました照合 - 1つはlatin1_swedish_ciで、もう1つはuft8_general_ciでした。

私は、クエリUTF8にそれらの両方を送信した後(2.7秒から0.002秒まで)大幅に高速化された

関連する問題