0

12列を超えるテーブルを取得しました。これは、最新の7つのレコードを取得するために使用されるmysqlクエリです。

SELECT * FROM data WHERE user_id IN(12,10,7,1) HAVING continent IN('Europe','America','Australia') AND NOT MATCH(weather) AGAINST('+"[blues]"' IN BOOLEAN MODE) || continent = 'Asia' AND MATCH(weather) AGAINST('+"[purples]"' IN BOOLEAN MODE) ORDER BY tb_id DESC LIMIT 7

合計行数は以上で5 millionありuser_id、インデックス付きの列tb_idですPRIMARY KEYEXPLAINの前で使用する場合SELECT。MySQLは、合計500万から40万を超えるレコードを読み取ると言っています。

では、大陸の列にインデックスを付ける必要がありますか、それともこの場合は役に立ちませんか?

これがEXPLAINの結果です

id = 1; select_type = SIMPLE; table = data; possible_keys = user_id; key = user_id; ref = NULL; rows = 582; Extra = Using where, Using filesort

4

1 に答える 1

1

まず第一に、あなたのクエリはおそらく間違っています。ORwhereまたはhave句またはwhereと混合して使用する場合ANDは、paranthesesを使用する必要があります。

第二に、あなたのケースでHAVINGを使用することは意味がなく、オプティマイザーはおそらくそれをWHERE句に変換します。

2つの違いは、WHERE選択する行を決定するときに適用されることです。HAVING結果セットに適用されます。したがって、オプティマイザが適切に機能しない場合は、最初に(ほぼ)すべての行を取得してから、それらをフィルタリングします。すべてをWHERE句に入れると、関連する行のみが取得されます。HAVING(ほぼ)を使用している場合にのみ意味がありますGROUP BY

したがって、次のようにクエリを作成することをお勧めします。

SELECT * FROM data 
WHERE user_id IN(12,10,7,1) AND
(
(
continent IN('Europe','America','Australia') 
AND NOT MATCH(weather) AGAINST('+"[blues]"' IN BOOLEAN MODE) 
)
OR 
(
continent = 'Asia' 
AND MATCH(weather) AGAINST('+"[purples]"' IN BOOLEAN MODE) 
)
)
ORDER BY tb_id DESC LIMIT 7

インデックスに関する質問に答えるには、テーブルのexplainステートメントとcreateステートメントの結果を投稿してくださいdata

于 2013-02-06T10:12:19.163 に答える