3
SELECT count(*) c FROM full_view WHERE verified > ( DATE (NOW()) - INTERVAL 30 DAY)

そのクエリを実行すると一瞬かかりますが、比較演算子を切り替えると何百年もかかります。最初の方法ではカウント = 0、2 番目の方法ではカウント = 120000 ですが、テーブル全体をカウントすると、マイクロ秒もかかります。

しかし、クエリが終了した場合、その後は非常に高速に実行されるため、何か奇妙なことが起こっています。MySQL はクエリまたは何かをキャッシュしていますか? Web サイトがハングアップしないようにするためにキャッシュに依存したくありません。

これは無意味に思えます: 特定の日付よりも後のすべてをすばやくカウントできる場合、反対の日付をカウントするのになぜこれ以上時間がかかるのでしょうか? いずれにせよ、テーブル全体を見なければなりませんよね?また、返す必要があるのは数値だけなので、帯域幅は問題になりません。

クエリについて説明します。

1, 'SIMPLE', 'b', 'range', 'updated,verified_index', 'updated', '3', '', 28, 'Using where'`    
1, 'SIMPLE', 'l', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'xyz_main.b.loc_id', 1, 'Using index'
1, 'SIMPLE', 'f', 'ALL', '', '', '', '', 2214, ''

編集:

これは興味深いかもしれません。クエリを実行すると、次の情報が見つかりました。

Handler_read_rnd_next:

  • 254436689 (未満の場合)
  • 2 (より大きい)

Key_read_requests: 314393 対 33 (より大きい値を使用する場合、33 はすべての統計の最大数です)

Handler_read_key: 104303 対 1

ビューをバイパスし、クエリをメイン テーブルで直接実行すると、速度が低下しなくなります。では、高速化するにはどうすればよいでしょうか。ビューは基本的に次のようになります。

SELECT x, y, z, verified FROM table1 LEFT JOIN table2 on tab2_ID = table2.ID LEFT JOIN table3 on tab3_ID = table3.ID

解決済み: フランキーは私を正しい方向に導きました。2 番目の結合テーブル (会社テーブル) は、会社のフルテキスト名を介して結合されました。そのテーブルに整数キーを追加することにしたのはつい最近のことです。name 列はインデックス化されるはずでしたが、それを失敗した可能性があります。とにかく、私はすべてを再編成しました。メイン テーブルの外部キーを、完全な会社名ではなく会社テーブルの整数 ID に一致するように変換しました。各テーブルでこれらの列のインデックスを再作成し、新しい結合ポイントを反映するようにビューを更新しました。これで、両方向に即座に実行されます。:) だから、整数キーが鍵だったと思います。問題は解決しましたが、元の質問が本当に解決されたようには感じません。

助けてくれてありがとう。

4

4 に答える 4

3

以下のクエリを実行し、結果を投稿してください。

EXPLAIN SELECT count(*) c 
FROM full_view 
WHERE verified > ( DATE (NOW()) - INTERVAL 30 DAY)

長い間忘れられていたEXPLAINものは、ほとんどの場合、何かをもたらします。; )


編集1:
これはおそらく攻撃的な行です:

1, 'SIMPLE', 'f', 'ALL', '', '', '', '', 2214, ''

そこALLには、FULL テーブル スキャンがあることが示されています。

Explainこの図の構文をさらに掘り下げることができます。

違いがどこにあるのか見てみてください...


編集 2:
このドキュメントにより、出力がより明確になりExplainます。チェックアウトしてください。


編集 3:
Explain コマンドの段階的な分析。

1, 'SIMPLE', 'b', 'range', 'updated,verified_index', 'updated', '3', '', 28, 'Using where'`    
1 - id
SIMPLE - simple select, not using sub-queries
b - table name
range - only rows that are in a given range are retrieved, using an index
updated,verified_index - are both possible keys
updated - was the key eventually used
3 - key lenght
'' - this is the ref column and would show which columns or constants are compared to the index name in the key column to select rows from the table.
28 - number of rows mysql believes it must examine to execute the query
Using where - self explanatory
于 2010-08-19T23:27:11.730 に答える
2

私の推測では、 からの減算がDate(Now())処理に時間がかかっているのです。の値verifiedがすでに 未満である場合Date(Now())、その時点で false でなければならないため (「より大きい」を比較する場合)、評価は短絡する可能性があります。

「より小さい」と比較している状況では、現在の値に関係なく、すべての場合に日時を減算する必要があります。これは、日時の減算を評価する前に式が真または偽であると論理的に結論付ける方法がないためです。

ただし、これは推測に過ぎません。

于 2010-08-19T23:22:38.210 に答える
1

30 日以上前に確認されたレコードがないことをデータベース エンジンに伝える統計がある場合があります。その場合、テーブルをまったく読み取る必要はなく、統計ヒストグラムから情報を取得します。

于 2010-08-19T23:25:16.477 に答える
0

テーブルにインデックスがある場合はverified、より制限的なCOUNTもの (> のもの) の方が高速になります。テーブル/インデックス統計からカウントを収集できるため、WHERE 句のない COUNT(*) はすぐに返されます。

于 2010-08-19T23:23:09.637 に答える