1

次のテーブルがあります(例)

t1 (20.000 rows, 60 columns, primary key t1_id)
t2 (40.000 rows, 8 columns, primary key t2_id)
t3 (50.000 rows, 3 columns, primary key t3_id)
t4 (30.000 rows, 4 columns, primary key t4_id)

SQL クエリ:

SELECT COUNT(*) AS count FROM (t1)
JOIN t2 ON t1.t2_id = t2.t2_id
JOIN t3 ON t2.t3_id = t3.t3_id
JOIN t4 ON t3.t4_id = t4.t4_id

結合に影響する列 (例: t1.t2_id) と必要に応じて外部キーにインデックスを作成しました。クエリが遅く (600 ミリ秒)、where 句 (たとえばWHERE t1.column10 = 1、 wherecolumn10にインデックスがない) を配置すると、クエリが大幅に遅くなります。私が行うクエリは高速であり、カウント動作を理解できませんselect (*)LIMIT解決策はありますか?

編集:追加されたSQLの説明

id  select_type     table   type    possible_keys   key     key_len     ref  rows   Extra
1   SIMPLE          t4      index   PRIMARY     user_id     4           NULL  5259  Using index
1   SIMPLE          t2      ref     PRIMARY,t4_id   t4_id   4        t4.t4_id   1   Using index
1   SIMPLE          t1      ref     t2_id         t2_id     4        t2.t2_id   1   Using index
1   SIMPLE          t3      ref     PRIMARY     PRIMARY     4        t2.t2_id   1   Using index

user_id は t4 テーブルの列です

編集: innodb から myisam に変更したところ、特に where 句を配置した場合に速度が向上しました。しかし、まだ時間があります (100 ~ 150 ミリ秒) アプリケーションでカウントが必要な理由は、検索フォームを処理しているユーザーに対して、彼が ajax で期待している結果の数です。これには、1 時間ごとに更新される一時テーブルを作成するなど、より良い解決策があるのでしょうか?

4

3 に答える 3

1

カウント クエリは、クエリ プランに記載されているように、INDEX ONLY SCAN により単純に高速です。あなたが言及したクエリは、インデックス付きの列のみで構成されているため、実行中に物理データに触れる必要はありません。すべてのクエリはインデックスに対して実行されます。インデックスが作成されていない列、またはインデックスの使用を妨げる方法でインデックスが作成された列で構成される追加の句を配置すると、ヒープ テーブルに格納されているデータに物理アドレスでアクセスする必要があり、これは非常に低速です。

編集: もう 1 つの重要なことは、それらは PK であるため、一意であるということです。オプティマイザーは、最初のインデックスで INDEX RANGE SCAN を実行することを選択し、キーが後続のインデックスに存在するかどうかのみをチェックします (そのため、計画では 1 行のみが返されると述べられています)。

EDIT2:J. BruniへのThx、実際には上記のクラスタ化されたインデックスは「完全な真実」ではありません。おそらく、最初のテーブルでフル スキャンが行われ、FK の存在を確認するために 3 つの後続の INDEX ACCESS が行われます。

于 2012-09-16T12:38:53.703 に答える
0

count結果セット全体を反復し、インデックスに依存しません。クエリに EXPLAIN ANALYZE を使用して、クエリがどのように実行されるかを確認します。

select + limit は結果セット全体を反復しないため、高速です

于 2012-09-16T12:22:17.563 に答える
-1

遅いパフォーマンスについてCOUNT(*): InnoDB エンジンを使用していますか? 見る:

主な情報は次のようです:「InnoDB はクラスター化された主キーを使用するため、主キーは行と一緒にデータ ページに格納され、個別のインデックス ページには格納されません。

そのため、考えられる解決策の 1 つは、個別のインデックスを作成USE INDEXし、SQL クエリでコマンドを使用してその使用を強制することです。使用状況レポートのサンプルについては、このコメントをご覧ください。

http://www.mysqlperformanceblog.com/2006/12/01/count-for-innodb-tables/comment-page-1/#comment-529049

この問題に関してはWHERE、次のように条件を JOIN 句に入れると、クエリのパフォーマンスが向上します。

SELECT COUNT(t1.t1_id) AS count FROM (t1)
JOIN t2 ON (t1.column10 = 1) AND (t1.t2_id = t2.t2_id)
JOIN t3 ON t2.t3_id = t3.t3_id
JOIN t4 ON t3.t4_id = t4.t4_id
于 2012-09-16T12:22:56.040 に答える