2017-12-21 12 views
3

テーブルに正しいインデックスがあっても実行に約90秒かかるクエリがあります。なぜか分からない。よくインデクシングされた2つのテーブルの1つのINNER JOINが実行に1分以上かかります

私はMySQLを使用しており、テーブルはInnoDBです。

これはクエリです:

SELECT count(*) 
FROM `following_lists` fl INNER JOIN users u 
ON fl.user_uuid = u.user_uuid 
WHERE fl.following_query_id = 1000010 AND u.status <= 2 

私はこのクエリは、テーブルfollowing_listsに開始WHERE条件につき、約4Kレコードをつかむ、主キーでテーブルusersにこれらのレコードを結合、チェックすることを期待ユーザーテーブル内のフィールドの値を返し、結果のレコードの数を返します。どうしてそんなに長い時間がかかりますか?私がテーブルに加わっている2つのフィールドはCHAR(40)で整数ではないからでしょうか?

これらは、関係のテーブルとそのインデックス、次のとおりです。

CREATE TABLE `users` ( 
    `user_uuid` CHAR(40) NOT NULL, 
    `status` TINYINT UNSIGNED NOT NULL, 
    ... 

    PRIMARY KEY (`user_uuid`), 
    ... 
) 

CREATE TABLE `following_lists` ( 
    `following_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    `following_query_id` INT UNSIGNED NOT NULL, 
    `user_uuid` CHAR(40) NOT NULL, 

    PRIMARY KEY (`following_id`), 
    KEY `query_id` (`following_query_id`), 
    KEY `user_uuid` (`user_uuid`) 
) 

そして、これは説明クエリの出力です:

+----+-------------+-------+--------+--------------------+----------+---------+--------------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len |  ref  | rows | Extra | 
+----+-------------+-------+--------+--------------------+----------+---------+--------------+------+-------------+ 
| 1 | SIMPLE  | fl | ref | query_id,user_uuid | query_id |  4 | const  | 3718 |    | 
| 1 | SIMPLE  | u  | eq_ref | PRIMARY   | PRIMARY |  160 | fl.user_uuid | 1 | Using index | 
+----+-------------+-------+--------+--------------------+----------+---------+--------------+------+-------------+ 

さらなる詳細:

  • テーブルfollowing_lists約25k行ありますが、3718だけがfl.following_query_id = 1000010です。

  • usersには約160KBの行がありますが、結合では3718だけを選択してください。両方の条件を満たすレコードは40レコードだけですfl.following_query_id = 1000010 AND u.status <= 2

  • 条件AND u.status <= 2を削除してもクエリが遅くなります。

+0

それはCHAR(40)である場合、私は驚かないだろう。整数値では、1つの比較が必要です。そのCHAR(40)で、最大40の比較が必要です。実際に必要な数は、CHAR(40)の実際の値に依存します。値の最初のX文字がすべて同じであれば、少なくともその数は多くなります。また、私が間違っていないと、MySQLのCHARインデックスは文字列全体をカバーしません。 – Uueerdo

+1

両方の列が同じ照合と文字セットを使用していますか? –

+1

他のよくある質問への回答を参照してください。 UUIDを使用してパフォーマンスを向上させる方法についての手がかりを与えるかもしれません。 https://stackoverflow.com/questions/2365132/uuid-performance-in-mysql/2365176 –

答えて

0

「死亡贈与」

MyISAMを使用している場合は、使用しないでください。代わりに、InnoDBに切り替えてください。

following_lists.idが必要ですか? (following_query_id, user_uuid)はユニークですか?その場合は、PRIMARY KEYにしてください。

あなたが上記の操作を行うことができない場合は、

INDEX(following_query_id, user_uuid) 

UUIDs

KEY `query_id` (`following_query_id`) 

を変更するには、不必要に必要なサイズよりも大きいとutf8mb4、またはCHARを宣言した場合は特に、非効率的なひどいです。 CHAR(36) CHARACTER SET asciiに変更してください。 ( `大幅に縮小EXPLAINで「160」に注目してください。)のUUIDは、パフォーマンスのために悪い理由

もっと上:http://mysql.rjweb.org/doc.php/uuid

あなたはどのくらいのRAMを持っていますか? innodb_buffer_pool_sizeの設定は何ですか? (それはあまりにも低いように聞こえる。インデックス上)

より:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

関連する問題