31

さまざまな列でさまざまなクエリのベンチマークを実行しようとしていますが、MySQL では実行できません。クエリを最初に実行した後、そのクエリの実行時間を同じにすることはできません。たとえば、クエリが最初に 0.062 秒で実行された場合、2 回目、3 回目などの実行で同じ実行時間を取得することはできません。0 秒または 0.015 のいずれかになります。

MySQLクエリキャッシュの無効化とクリアに関する多くの投稿を読みましたが、どれも役に立ちませんでした.

このSOの投稿がここにあるように

私が何をしようとも、MySQL はキャッシュされた結果を使用することを主張しているようです。

MySQL Workbench を再起動してから実行します。

set global query_cache_type=0;
set global query_cache_size=0;
flush query cache;
reset query cache;

実行時間は 0 秒を示し続けます。

変更できなかったサーバー変数は「have_query_cache」だけです。その値は「はい」で、「いいえ」に設定しようとすると、Workbench は読み取り専用であると言います。

私もそうです。

set profiling=1;
run my select query
show profile for query 2;

プロファイリングの結果は次のとおりです。

'starting', '0.000077'
'checking permissions', '0.000007'
'Opening tables', '0.000016'
'init', '0.000035'
'System lock', '0.000009'
'optimizing', '0.000013'
'statistics', '0.000094'
'preparing', '0.000008'
'executing', '0.000002'
'Sending data', '0.000016'
'end', '0.000002'
'query end', '0.000003'
'closing tables', '0.000005'
'freeing items', '0.000139'
'cleaning up', '0.000009'

私が間違っていなければ、これはキャッシュが正しく使用されていないことを示していますか? しかし、私はまだ0秒を見ています。実行時間のために。

編集:私が実行しているクエリは、次のような「SQL_NO_CACHE」を使用した SELECT クエリです。

SELECT SQL_NO_CACHE col1,now() from mytable where col2="some_value"

(クエリのキャッシュを防ぐために now() 関数を追加しました)

Edit2:innoDB、MySQL 5.6.10を使用しています

ここで何が起こっているのかわからないので、誰かが私を助けてくれませんか。

どうもありがとう!

4

5 に答える 5

7

バッファー プールのページ読み取りと、ページを取得するためにディスクに移動する必要があったページ読み取りの違いを確認できます。

mysql> SHOW SESSION STATUS LIKE 'Innodb_buffer_pool_read%';
mysql> ...run a query...
mysql> SHOW SESSION STATUS LIKE 'Innodb_buffer_pool_read%';

レポートのこれらの値を比較し、それらがどれだけ増加しているかを確認します。

+---------------------------------------+----------+
| Variable_name                         | Value    |
+---------------------------------------+----------+
| Innodb_buffer_pool_read_requests      | 10327490 |
| Innodb_buffer_pool_reads              | 1133     |
+---------------------------------------+----------+

read_requestsは論理ページ読み取りであり、既にバッファー プールにあるページから読み取ることができますこの数がクエリ後に増加しても、読み取りが増加しない場合、クエリはバッファー プールからのみ結果を取得しています。

読み取りは、ディスクに送信する必要があり、バッファー プールにページをコピーするための I/O のコストが発生するページ読み取りの数です。この数がクエリ後に増加する場合は、ディスクからデータをロードする必要がありました。

メモリ アクセスとディスク アクセスのパフォーマンスの違いの詳細については、http://everythingisdata.wordpress.com/2009/10/17/numbers-everyone-should-know/を参照してください。


あなたのコメントについて:

「オープニングテーブル」は、データディクショナリのような InnoDB テーブルのメモリ内キャッシュに関連しています。テーブルは、再起動後に最初に参照されたときに開かれます。インメモリ データ ディクショナリ内の特定のテーブルのエントリは無期限にメモリ内にとどまるため、数千のテーブルがある場合、メモリ使用量がかなり大きくなる可能性があります。MySQL 5.6 では、そのメモリ使用量に上限を設定し、使用頻度の低いテーブルを削除するためのいくつかの微調整変数があります。ただし、このメカニズム全体は、データとインデックスのページを格納するバッファー プールとは別のものです。

「統計」もバッファプールとは別のものです。InnoDB は、クエリ オプティマイザをガイドするために使用する、データとインデックスに関するインメモリ統計を維持します。InnoDB テーブルに初めてアクセスしたとき、SHOW TABLE STATUS を実行したとき、または INFORMATION_SCHEMA に対して特定のクエリを実行したとき、ANALYZE TABLE を実行したとき、およびテーブルのサイズが大幅に変更されたときに、統計は自動的に更新されます。InnoDB は、テーブルから一定数のページをランダムに読み取ってこれらの統計を生成します。コールド バッファー プールがある場合、これはディスクにヒットする可能性があります。

于 2013-04-17T00:11:23.773 に答える
4

わかった。だから私はこのinnoDBバッファプールの問題を掘り下げてきました。それについて言及してくれた@Quassnoi、@TheVedgeに感謝します。次の作業に大変役立ちました。

innoDB バッファー プールを無効化またはリセットする方法を見つけようとしましたが、MySQL サーバーを再起動する以外の方法を見つけることができませんでした。(Windows ボックスでサーバーを再起動するには、services.msc またはコマンド プロンプトを使用できます。)

すべての構成変数の設定と「SQL_NO_CACHE」の使用は、キャッシュの使用を回避するのに十分すぎると思います。また、プロファイリング結果を確認しても、キャッシュ参照は表示されませんでした (元の投稿を確認してください)。

次に、MySQL サーバーを再起動した後、同じクエリの 1 回目と 2 回目の実行のプロファイリングを確認することにしました。このようにして、クエリの実行中に何が起こっているかを段階的に確認できます。

サーバーの再起動後の最初の実行では、次の手順とタイミングが得られました。

'starting', '0.000078'
'checking permissions', '0.000005'
'Opening tables', '0.120329'
'init', '0.000107'
'System lock', '0.000012'
'optimizing', '0.000024'
'statistics', '0.065317'
'preparing', '0.000026'
'executing', '0.000003'
'Sending data', '0.000038'
'end', '0.000005'
'query end', '0.000006'
'closing tables', '0.000014'
'freeing items', '0.000463'
'cleaning up', '0.000039'

そして、これらは2回目の実行の結果です:

'starting', '0.000068'
'checking permissions', '0.000006'
'Opening tables', '0.000019'
'init', '0.000046'
'System lock', '0.000007'
'optimizing', '0.000010'
'statistics', '0.000073'
'preparing', '0.000009'
'executing', '0.000002'
'Sending data', '0.000035'
'end', '0.000003'
'query end', '0.000003'
'closing tables', '0.000006'
'freeing items', '0.000181'
'cleaning up', '0.000015'

ご覧のとおり、2 つの実行間で「テーブルを開く」アクションと「統計」アクションの期間に大きな違いがあり、いずれの実行もキャッシュを参照しません。

2 つのアクションは、最初の実行で最も時間がかかる部分のようです (innoDB バッファー プールの作成の一部と考えられます)。プールが生成されると、これら 2 つのアクションはそれほど重く実行されないため、実行時間が大幅に短縮されます。バッファー プール作成後のクエリ。

2 回目の実行の個々のステップの実行時間を合計すると、0.000483 秒になり、MySQL ワークベンチはこの結果を 0.000 秒として表示すると、2 回目の実行がキャッシュを使用した結果であると思わせるかもしれませんが、実際にはそうではない。これは、クエリの実行期間の表示精度の問題にすぎません。

その結果、これまでにわかったことは、キャッシュの使用を実際に無効にすることができたことであり、2 番目のクエリを大幅に高速化するのは innoDB バッファー プールの完成です。これは、0.000483 秒で 200 万行のレコードを見つけることができることも意味します。

同意しますか?

于 2013-04-16T22:42:12.387 に答える