5

テーブル内の400,000レコード

テーブル形成

id(int,pk)
title varchar(255)
body(text)

クエリ1

select **title** from qa_question order by id desc limit 300000, 15;

実行時間15

クエリ2

select **body** from qa_question order by id desc limit 300000, 15;

実行時間1.8

理由を知りたい

4

3 に答える 3

2

単純な、ORDER BYが最初に実行され、次にLIMITのみが機能します。非常に多くのレコードでIDで注文した場合 、大量のデータ(varcharとtext)が移動されていることを意味します。そこで注文しないと、データがそのように移動されないため、クエリが高速になります。データが多いほど、ディスクへのI/O要求が多く生成されます。

以下のコメントで質問に答えるため。

違いは、OPがMyISAMストレージエンジンを使用している可能性があり、そのためにTEXTが行に格納されていないことが原因である可能性があります。VARCHARはです。ここを参照してください。そのファイルシステムストレージは、行内ではなく行内で保存するためのソート時間の違いである可能性があります。この素敵な説明も読んでください

この投稿も参照してください

于 2013-01-21T08:25:37.063 に答える
1

を持っているクエリを詳しく見てみましょうORDER BY id DESC LIMIT 300000, 15

MySQLサーバーはそれを実行するために何をしなければなりませんか?まず、プライマリインデックスに従ってすべてのレコードidを降順でフェッチする必要があります。これは30万回発生する必要があることに注意してください。300,000カウントに達すると、サーバーは結果行の出力を開始でき、そのうち15行のみになります。300kの初期オフセットではなく、もっと小さいものを使用した場合、このクエリははるかに高速に機能します。

query1がquery2と10倍異なるのはなぜですか?これはTEXT、MySQLの列が(そこに格納されていない)親テーブルにリンクされており、それらを取得するには追加のルックアップが必要であるが、VARCHARテーブルに格納されているためです。あなたの場合、行300,000に到達するまでTEXT実際に列をプルする必要がないため、列が優先されます(サーバーは、別の非表示のテーブルの列への比較的小さな参照のみをプルします)。ただし、列の場合、サーバーは100バイトの範囲であっても、列全体をプルする以外に選択肢がありません。これが、10倍遅い理由です。bodybody TEXTtitletitle

正確に言うのは難しいです。これは、最初のクエリの実行速度が遅いが、すべてのテーブルデータをRAMにキャッシュしたため、2番目のクエリの実行速度が大幅に向上したことが原因である可能性があります。結論を出す前に、すべてのクエリを少なくとも3回繰り返す必要があります。

LIMIT 300000, 15あなたへの私の提案は、に置き換える方法を見つけることです

WHERE id BETWEEN 300000 AND 300014

または可能であれば同等のもの。この場合、サーバーはプライマリインデックスを利用できるようになり、非常に高速になります。

于 2013-01-21T08:38:30.370 に答える
0

これは、varcharがクエリが実行される前にメモリを割り当てるためです。つまり、静的メモリ割り当てを使用します。そのため、タイトルが255文字より短い場合でも、255文字のメモリが予約されます。

VARCHAR CHARACTER SET utf8を使用できますが、この場合は動的で、タイトルの長さに応じてメモリの量を使用するnvarcharのエイリアスです。

非常に多くの400,000レコードがあるため、varcharを使用している間は実行時間が長くなります。したがって、私の提案は、VARCHAR CHARACTER SET utf8を使用し、varcharの使用を避けることです。

于 2013-01-21T08:36:45.173 に答える