私はかなり大きなテーブル(1.8GB、25Mレコード)を持っており、すべての重要な列(WHEREまたは他のセレクターを使用しているもの)にインデックスがあります。エンジンはMyISAMで、InnoDBへの切り替えを推奨していると聞いていますが、他の多くの人は、カウントの観点から、大量のデータを使用するとMyISAMの方が高速であると述べています(安全なトランザクションにはInnoDBの方が適しています)。
今、時々、私は一連の単純な統計クエリを実行します(それで私たちは私たちがどこに立っているかを見ることができます):
(A) SELECT COUNT(username) FROM superLargeTable
(B) SELECT COUNT(username) FROM superLargeTable WHERE firstname IS NOT NULL
(C) SELECT COUNT(username) FROM superLargeTable WHERE firstname IS NULL
テーブルが最近更新された場合(そしてキャッシュが無効である場合)、これらは遅いクエリログによって測定されたクエリ時間です。
A:71秒(ロック:0秒)(行:1)B:47秒(ロック:0秒)(行:1)C:20秒(ロック:0秒)(行:1)
2回目の実行では、明らかに(キャッシュされているため)、ほぼ瞬時のデータが得られます。
関連するすべての列にインデックスがあります(ほとんどすべての列にインデックスがあります)。多くの列のインデックスは非常に悪い設計であると言って、私はまだ推奨事項に取り組んでいますが、それ以外の場合はクエリがすべてタイムアウトになるため、完全に必要です。
私はかなりの数のバーストタイプの挿入と更新を持っており、不規則な間隔で(時には毎分、最大5000の挿入/更新の高速バーストで)テーブルで起動し、時には数分間隔で起動します。
データは同期している必要があるため、読み取り専用のスレーブに分割してそれを操作することはできません。
単純なCOUNTに時間がかかる理由はありますか?単一の特定の基準で、行にあるレコードの数を教えてくれる秘密の代替コマンドはありますか?
本当に困惑しました。サーバーは8GHz、8 / 16GB RAM、160GBディスク(10%程度使用中)であり、クエリはすべてローカルで実行され、Web経由で転送されません。
必要に応じて、より多くのデータ/情報を喜んでお手伝いします。
編集1:クエリAのEXPLAINコマンドはこれを返します:
select_type=SIMPLE
type=index
possible_keys=NULL
key=followers (this is the actual username column in the imaginary query above)
key_len=9
ref=NULL
rows=24408162
Extra=Using index
編集2:@theHeは素晴らしいツールを推奨しました:mysqltuner.pl –結果(問題)は次のとおりです。
[!!] Total fragmented tables: 15
[!!] Maximum possible memory usage: 30.7G (767% of installed RAM)
[!!] Query cache efficiency: 8.6% (5M cached / 59M selects)
[!!] Joins performed without indexes: 19031
[!!] Temporary tables created on disk: 48% (993K on disk / 2M total)
[!!] Table cache hit rate: 0% (64 open / 27K opened)
そして、これらは推奨事項です:
-------- Recommendations -----------------------------------------------------
General recommendations:
Run OPTIMIZE TABLE to defragment tables for better performance
Reduce your overall MySQL memory footprint for system stability
Adjust your join queries to always utilize indexes
When making adjustments, make tmp_table_size/max_heap_table_size equal
Reduce your SELECT DISTINCT queries without LIMIT clauses
Increase table_cache gradually to avoid file descriptor limits
Variables to adjust:
*** MySQL's maximum memory usage is dangerously high ***
*** Add RAM before increasing MySQL buffer variables ***
query_cache_limit (> 10M, or use smaller result sets)
join_buffer_size (> 128.0K, or always use indexes with joins)
tmp_table_size (> 32M)
max_heap_table_size (> 16M)
table_cache (> 64)