2017-06-01 1 views
1

10Mから500Mの大きな行数を持つMyISAMテーブルがあります。テーブルは時系列データをまれに格納するために使用されており、私はのために最適化したいと思います。これは、エポックと分類子列(数千のカテゴリを含む)の2つのインデックスです。MySQL - テーブルインデックスまたはテーブルデータへのアクセスが遅い

私の問題は、SQL_NO_CACHEを使用していても、特定のカテゴリの最初のSELECTはかなり長く(10〜50秒)、次のものは本当に高速です。このようなクエリは通常、100,000〜1Mの要素を返します。

プロファイリングでは、MySQLが「送信データ」に多くの時間を費やしていることがわかります。これは、多くの時間がディスクI/Oを実行していることを示します。しかし、私は実際にボトルネックがどこにあるのか分かりません:

  1. BTREEのボトルネックは読んでいますか?ツリーは、選択されたノード内に数千個のノードしかなく、1Mポイント未満しかありません。古い学校のハードドライブを使っていても、現代のマシンでは30秒かかるとは思えません。
  2. テーブルの行を読み取っていますか?それは〜40bytesの平均長さを持つ百万行未満です。
  3. 他に何かを考慮していないのですか?ここで

クエリの結果は次のとおりです。

mysql> SELECT SQL_NO_CACHE COUNT(`Time`) FROM archive_1 WHERE Channel=63; 
+---------------+ 
| COUNT(`Time`) | 
+---------------+ 
|  450619 | 
+---------------+ 
1 row in set (28.67 sec) 

mysql> SELECT SQL_NO_CACHE COUNT(`Time`) FROM archive_1 WHERE Channel=63; 
+---------------+ 
| COUNT(`Time`) | 
+---------------+ 
|  450619 | 
+---------------+ 
1 row in set (2.20 sec) 

mysql> SELECT SQL_NO_CACHE COUNT(`Time`) FROM archive_1 WHERE Channel=63; 
+---------------+ 
| COUNT(`Time`) | 
+---------------+ 
|  450619 | 
+---------------+ 
1 row in set (0.88 sec) 

mysql> SHOW PROFILES; 
+----------+-------------+-----------------------------------------------------------------------------------+ 
| Query_ID | Duration | Query                    | 
+----------+-------------+-----------------------------------------------------------------------------------+ 
|  1 | 28.66720725 | SELECT SQL_NO_CACHE COUNT(`Time`) FROM archive_1 WHERE Channel=63 | 
|  2 | 2.19872350 | SELECT SQL_NO_CACHE COUNT(`Time`) FROM archive_1 WHERE Channel=63 | 
|  3 | 0.87811475 | SELECT SQL_NO_CACHE COUNT(`Time`) FROM archive_1 WHERE Channel=63 | 
+----------+-------------+-----------------------------------------------------------------------------------+ 
3 rows in set (0.00 sec) 

mysql> SHOW PROFILE FOR QUERY 1; 
+----------------------+-----------+ 
| Status    | Duration | 
+----------------------+-----------+ 
| starting    | 0.000113 | 
| checking permissions | 0.000010 | 
| Opening tables  | 0.000027 | 
| System lock   | 0.000017 | 
| init     | 0.000030 | 
| optimizing   | 0.000018 | 
| statistics   | 0.055731 | 
| preparing   | 0.000024 | 
| executing   | 0.000008 | 
| Sending data   | 28.611161 | 
| end     | 0.000019 | 
| query end   | 0.000005 | 
| closing tables  | 0.000014 | 
| freeing items  | 0.000021 | 
| logging slow query | 0.000003 | 
| logging slow query | 0.000004 | 
| cleaning up   | 0.000005 | 
+----------------------+-----------+ 
17 rows in set (0.00 sec) 

mysql> SHOW PROFILE FOR QUERY 2; 
+----------------------+----------+ 
| Status    | Duration | 
+----------------------+----------+ 
| starting    | 0.000105 | 
| checking permissions | 0.000011 | 
| Opening tables  | 0.000036 | 
| System lock   | 0.000015 | 
| init     | 0.000028 | 
| optimizing   | 0.000019 | 
| statistics   | 0.032255 | 
| preparing   | 0.000024 | 
| executing   | 0.000007 | 
| Sending data   | 2.166140 | 
| end     | 0.000020 | 
| query end   | 0.000004 | 
| closing tables  | 0.000014 | 
| freeing items  | 0.000025 | 
| logging slow query | 0.000003 | 
| cleaning up   | 0.000018 | 
+----------------------+----------+ 
16 rows in set (0.00 sec) 

mysql> SHOW PROFILE FOR QUERY 3; 
+----------------------+----------+ 
| Status    | Duration | 
+----------------------+----------+ 
| starting    | 0.000071 | 
| checking permissions | 0.000009 | 
| Opening tables  | 0.000018 | 
| System lock   | 0.000012 | 
| init     | 0.000021 | 
| optimizing   | 0.000014 | 
| statistics   | 0.000059 | 
| preparing   | 0.000020 | 
| executing   | 0.000007 | 
| Sending data   | 0.877795 | 
| end     | 0.000021 | 
| query end   | 0.000004 | 
| closing tables  | 0.000015 | 
| freeing items  | 0.000029 | 
| logging slow query | 0.000015 | 
| cleaning up   | 0.000006 | 
+----------------------+----------+ 
16 rows in set (0.00 sec) 

私が照会しています特定のテーブルには、4237427600バイトのデータ長と4255541248バイトのインデックス長と107407213個の行が含まれています。私は昨日それを最適化しました。

クエリがI/Oバウンドの場合は、いつでもSSDに切り替えることができます。また、タイムインデックスをダブルではなく整数として格納するオプションもあります。しかし、これまでのところ私はボトルネックがどこにあるのか分からず、もっと知る前に大きな変化を避けたいと思っています。

+0

初めてクエリを実行すると、キャッシュに何もありません.2回目にキャッシュにデータがあるため、クエリの実行は高速です。 – xachela

答えて

2

SQL_NO_CACHEは、mysqlがクエリキャッシュを使用すべきでないことを意味します。

ディスク/バッファー・キャッシュが引き続き使用されているため、最初の照会に時間がかかり、後続の照会が高速になります。

+0

ありがとうございます。数学をすると、私は約30MBで約20MBを取り込み、約600KB /秒の読み取りスループットにつながります。ハードディスクにランダムに読み込む場合は1MB /秒に非常に近い。私はパフォーマンスを改善したいのならSSDに切り替える必要があると思います。 –

+0

@EnguerranPetitfils InnoDBを使用している場合は、(チャネル、時刻)でマルチカラムインデックスを作成できます。そのインデックスは、クエリ全体をカバーし、テーブルデータを読み込む必要はありません。 – Mikpa

+0

残念ながら、私はそれよりも多くのデータを回復していますが、上に示したクエリは物事を調査するためだけです。しかし、それは本当に良いアイデアです –

関連する問題