0

MySQL の奇妙な動作に遭遇しています。クエリの実行 (例: Explain [QUERY] で示されるインデックスの使用) と実行に必要な時間は、where 句の要素に依存します。

問題が発生するクエリは次のとおりです。

select distinct
e1.idx, el1.idx, r1.fk_cat, r2.fk_cat
from ent e1, ent_leng el1, rel_c r1, _tax_c t1, rel_c r2, _tax_c t2
where el1.fk_ent=e1.idx
and r1.fk_ent=e1.idx and ((r1.fk_cat=43) or (r1.fk_cat=t1.fk_cat1 and t1.fk_cat2=43))
and r2.fk_ent=e1.idx and ((r2.fk_cat=10) or (r2.fk_cat=t2.fk_cat1 and t2.fk_cat2=10))

対応する Explain 出力は次のとおりです。

| id | select_type | table | type   | possible_keys           | key     | key_len | ref           | rows  | Extra                       
+----+-------------+-------+--------+-------------------------+---------+---------+---------------+-------+------------------------------------
|  1 | SIMPLE      | el1   | index  | fk_ent                  | fk_ent  | 4       | NULL          | 15002 | Using index; Using temporary
|  1 | SIMPLE      | e1    | eq_ref | PRIMARY                 | PRIMARY | 4       | DB.el1.fk_ent |     1 | Using index
|  1 | SIMPLE      | r1    | ref    | fk_ent,fk_cat,fks       | fks     | 4       | DB.e1.idx     |     1 | Using where; Using index
|  1 | SIMPLE      | r2    | ref    | fk_ent,fk_cat,fks       | fks     | 4       | DB.el1.fk_ent |     1 | Using index
|  1 | SIMPLE      | t1    | index  | fk_cat1,fk_cat2,fk_cats | fk_cats | 8       | NULL          |    69 | Using where; Using index; Distinct; 
|    |             |       |        |                         |         |         |               |       | Using join buffer
|  1 | SIMPLE      | t2    | index  | fk_cat1,fk_cat2,fk_cats | fk_cats | 8       | NULL          |    69 | Using where; Using index; Distinct;  
                                                                                                          | Using join buffer

ご覧のとおり、1 列のインデックスには、それが属する列と同じ名前が付いています。また、使用されているものと一緒にいくつかの役に立たないインデックスも追加しました。それらが実行を変更するかどうかを確認するためです (変更されません)。

実行には約 4.5 秒かかります。

列 entl1.name を選択部分に追加すると (他に何も変更されていません)、el1 のインデックス fk_ent は使用できなくなります。

| id | select_type | table | type   | possible_keys           | key     | key_len | ref           | rows  | Extra                       
+----+-------------+-------+--------+-------------------------+---------+---------+---------------+-------+------------------------------------
|  1 | SIMPLE      | el1   | ALL    | fk_ent                  |  NULL   | NULL    | NULL          | 15002 | Using temporary

実行には約 8.5 秒かかります。

私は常に、クエリの選択部分はエンジンによるインデックスの使用に影響を与えず、そのような方法でパフォーマンスに影響を与えることはないと考えていました。

属性を除外することは解決策ではなく、さらに多くの属性を選択する必要があります。さらに悪いことに、使用されている形式のクエリはさらに複雑であり、パフォーマンスの問題が大きな問題になります。

私の質問は次のとおりです。1) この奇妙な動作の理由は何ですか? 2) パフォーマンスの問題を解決するにはどうすればよいですか?

ご協力いただきありがとうございます!グレッド

4

2 に答える 2

2

それは DISTINCT 制限です。これは、別の WHERE 制限と考えることができます。選択リストを変更すると、実際には DISTINCT 制限の WHERE 句が変更され、オプティマイザはとにかくテーブル スキャンを実行する必要があると判断するため、インデックスを使用しない可能性があります。

編集:

これが役立つかどうかはわかりませんが、データを正しく理解していれば、次のように DISTINCT 制限を取り除くことができると思います:

select
e1.idx, el1.idx, r1.fk_cat, r2.fk_cat
from ent e1
  Inner Join ent_leng el1 ON el1.fk_ent=e1.idx
  Inner Join rel_c r1 ON r1.fk_ent=e1.idx
  Inner Join rel_c r2 ON r2.fk_ent=e1.idx
where 
 ((r1.fk_cat=43) or Exists(Select 1 From _tax_c t1 Where r1.fk_cat=t1.fk_cat1 and t1.fk_cat2=43)) 
 and 
 ((r2.fk_cat=10) or Exists(Select 1 From _tax_c t2 Where r2.fk_cat=t2.fk_cat1 and t2.fk_cat2=10))
于 2010-09-22T15:16:43.663 に答える