3

私はこのクエリを持っています:-

SELECT SUM(DISTINCT( ttagrels.id_tag IN ( 1816, 2642, 1906, 1398,
                                          2436, 2940, 1973, 2791, 1389 ) )) AS
       key_1_total_matches,
       IF(( od.id_od > 0 ), COUNT(DISTINCT( od.id_od )), 0)                 AS
       tutor_popularity,
       td.*,
       u.*
FROM   tutor_details AS td
       JOIN users AS u
         ON u.id_user = td.id_user
       JOIN all_tag_relations AS ttagrels
         ON td.id_tutor = ttagrels.id_tutor
       LEFT JOIN learning_packs AS lp
         ON ttagrels.id_lp = lp.id_lp
       LEFT JOIN learning_packs_categories AS lpc
         ON lpc.id_lp_cat = lp.id_lp_cat
       LEFT JOIN learning_packs_categories AS lpcp
         ON lpcp.id_lp_cat = lpc.id_parent
       LEFT JOIN learning_pack_content AS lpct
         ON ( lp.id_lp = lpct.id_lp )
       LEFT JOIN webclasses AS wc
         ON ttagrels.id_wc = wc.id_wc
       LEFT JOIN learning_packs_categories AS wcc
         ON wcc.id_lp_cat = wc.id_wp_cat
       LEFT JOIN learning_packs_categories AS wccp
         ON wccp.id_lp_cat = wcc.id_parent
       LEFT JOIN order_details AS od
         ON td.id_tutor = od.id_author
       LEFT JOIN orders AS o
         ON od.id_order = o.id_order
WHERE  ( u.country = 'IE'
          OR u.country IN ( 'INT' ) )
       AND u.status = 1
       AND CASE
             WHEN ( lp.id_lp > 0 ) THEN lp.id_status = 1
                                        AND lp.published = 1
                                        AND lpcp.status = 1
                                        AND ( lpcp.country_code = 'IE'
                                               OR lpcp.country_code IN ( 'INT' )
                                            )
             ELSE 1
           END
       AND CASE
             WHEN ( wc.id_wc > 0 ) THEN wc.wc_api_status = 1
                                        AND wc.id_status = 1
                                        AND wc.wc_type = 0
                                        AND
             wc.class_date > '2010-06-16 11:44:40'
                                        AND wccp.status = 1
                                        AND ( wccp.country_code = 'IE'
                                               OR wccp.country_code IN ( 'INT' )
                                            )
             ELSE 1
           END
       AND CASE
             WHEN ( od.id_od > 0 ) THEN od.id_author = td.id_tutor
                                        AND o.order_status = 'paid'
                                        AND CASE
             WHEN ( od.id_wc > 0 ) THEN od.can_attend_class = 1
             ELSE 1
                                            END
             ELSE 1
           END
       AND ( ttagrels.id_tag IN ( 1816, 2642, 1906, 1398,
                                  2436, 2940, 1973, 2791, 1389 ) )
GROUP  BY td.id_tutor
HAVING key_1_total_matches = 1
ORDER  BY tutor_popularity DESC,
          u.surname ASC,
          u.name ASC
LIMIT  0, 20 

IN() 内の数値は、実際には、ユーザーが入力した検索キーワードに一致した、Tags という別のテーブルの ID です。この例では、ユーザーは「クラス」を検索しました。

ここで、このクエリの説明出力を参照してください:- http://www.test.examvillage.com/Screenshot.png

このクエリにかかる時間は 0.0536 秒です

ただし、() 内の ttagrels.id_tag の値の数が増えると (ユーザーがより多くの検索キーワードを入力するにつれて)、実行時間は約 1 ~ 5 秒以上に上昇します。学生は1日3回」
の実行時間は4.2226秒です。このクエリの Explain Query 出力には、2513 行が含まれています。

All_Tag_Relations テーブルには合計 6,152 のレコードがあります。さらなる最適化は可能ですか?

4

1 に答える 1

0

私はあなたのデータベースを知らないので、決定的な答えを出すことはできません。

あなたのクエリでDistinctキーワードが 2 回SUM(DISTINCT(COUNT(DISTINCT()

これは、select ステートメントが同じ id_tag または id_od を持つ複数の行を返すことを意味します。これは、グループ化前の中間結果に多くの行が含まれていることを意味します。行を制限するには、where 句を絞り込む必要があります。

クエリにcount(*)を挿入し、行数を確認します。予想よりも大きい場合は、これで問題が説明されます。

于 2013-08-10T08:47:39.680 に答える