1

私はmysqlクエリを持っており、where句を 使用すると正常に動作しますが、 where句を使用しないと、出力が得られず、最終的にタイムアウトします。実際、私はExplainコマンドを使用してクエリのパフォーマンスをチェックしましたが、どちらの場合も、Explainは結合に使用されたのと同じ数の行を提供します。Explainコマンドで取得した出力の画像を添付しました。以下はクエリです。ここで何が問題なのかわかりませんでした。どんな助けでも大歓迎です。ありがとう。

 SELECT 
        MCI.CLIENT_ID AS CLIENT_ID, MCI.NAME AS CLIENT_NAME, MCI.PRIMARY_CONTACT AS CLIENT_PRIMARY_CONTACT, 
        MCI.ADDED_BY AS SP_ID, CONCAT(MUD_SP.FIRST_NAME, ' ', MUD_SP.LAST_NAME) AS SP_NAME, 
        MCI.FK_PROSPECT_ID AS PROSPECT_ID, MCI.DATE_ADDED AS ADDED_ON,
        (SELECT GROUP_CONCAT(LT.TAG_TEXT SEPARATOR ', ') 
            FROM LK_TAG LT
            INNER JOIN M_OBJECT_TAG_MAPPING MOTM
            ON LT.PK_ID = MOTM.FK_TAG_ID
            WHERE MOTM.FK_OBJECT_ID = MCI.FK_PROSPECT_ID
                AND MOTM.OBJECT_TYPE = 1
                AND MOTM.IS_ACTIVE = 1
        ) AS TAGS,
        IFNULL(SUM(GET_DIGITS(MMR.RCP_AMOUNT)), 0) AS REVENUE_SO_FAR,
        IFNULL(SUM(GET_DIGITS(MMR.RCP_RUPEES)), 0) AS REVENUE_INR,
        COUNT(DISTINCT PMI_MONTHLY.PROJECT_ID) AS MONTHLY,
        COUNT(DISTINCT PMI_FIXED.PROJECT_ID) AS FIXED,
        COUNT(DISTINCT PMI_HOURLY.PROJECT_ID) AS HOURLY,
        COUNT(DISTINCT PMI_ANNUAL.PROJECT_ID) AS ANNUAL,
        COUNT(DISTINCT PMI_CURRENTLY_RUNNING.PROJECT_ID) AS CURRENTLY_RUNNING_PROJECTS,
        COUNT(DISTINCT PMI_YET_TO_START.PROJECT_ID) AS YET_TO_START_PROJECTS,
        COUNT(DISTINCT PMI_TECH_SALES_CLOSED.PROJECT_ID) AS TECH_SALES_CLOSED_PROJECTS
    FROM 
        M_CLIENT_INFO MCI
        INNER JOIN M_USER_DETAILS MUD_SP
            ON MCI.ADDED_BY = MUD_SP.PK_ID
        LEFT OUTER JOIN M_MONTH_RECEIPT MMR
                ON MMR.CLIENT_ID = MCI.CLIENT_ID
        LEFT OUTER JOIN M_PROJECT_INFO PMI_FIXED
                ON PMI_FIXED.CLIENT_ID =  MCI.CLIENT_ID AND PMI_FIXED.PROJECT_TYPE = 1
        LEFT OUTER JOIN M_PROJECT_INFO PMI_MONTHLY
                ON PMI_MONTHLY.CLIENT_ID =  MCI.CLIENT_ID AND PMI_MONTHLY.PROJECT_TYPE = 2
        LEFT OUTER JOIN M_PROJECT_INFO PMI_HOURLY
                ON PMI_HOURLY.CLIENT_ID =  MCI.CLIENT_ID AND PMI_HOURLY.PROJECT_TYPE = 3
        LEFT OUTER JOIN M_PROJECT_INFO PMI_ANNUAL
                ON PMI_ANNUAL.CLIENT_ID =  MCI.CLIENT_ID AND PMI_ANNUAL.PROJECT_TYPE = 4
        LEFT OUTER JOIN M_PROJECT_INFO PMI_CURRENTLY_RUNNING
                ON PMI_CURRENTLY_RUNNING.CLIENT_ID =  MCI.CLIENT_ID AND PMI_CURRENTLY_RUNNING.STATUS = 4
        LEFT OUTER JOIN M_PROJECT_INFO PMI_YET_TO_START
                ON PMI_YET_TO_START.CLIENT_ID =  MCI.CLIENT_ID AND PMI_YET_TO_START.STATUS < 4
        LEFT OUTER JOIN M_PROJECT_INFO PMI_TECH_SALES_CLOSED
                ON PMI_TECH_SALES_CLOSED.CLIENT_ID =  MCI.CLIENT_ID AND PMI_TECH_SALES_CLOSED.STATUS > 4
               WHERE YEAR(MCI.DATE_ADDED) = '2012'
                GROUP BY MCI.CLIENT_ID ORDER BY CLIENT_NAME ASC  

ここに画像の説明を入力

4

3 に答える 3

0

私は次のことを試してみます。まず、MySQL にはキーワード「STRAIGHT_JOIN」があり、オプティマイザに、指定したテーブルの順序でクエリを実行するよう指示します。すべての左結合は子関連 (参照テ​​ーブルなど) であるため、MySQL がそれらの 1 つをクエリの主な基礎として解釈しようとしないようにする必要があります。

SELECT STRAIGHT_JOIN ... 残りのクエリ。

次に、M_PROJECT_INFO テーブルです。データの列がいくつあるかわかりませんが、DISTINCT 集計のいくつかの列に集中しているようです。上のインデックスを介してクエリを支援するために、これらの要素にカバー インデックスがあることを確認します。

( Client_ID、Project_Type、Status、Project_ID )

このようにして、エンジンは条件を適用し、クエリのために生データ ページに戻る必要なく、インデックスから個別のデータをすべて取得できます。

3 つ目は、M_CLIENT_INFO テーブルです。両方の基準にインデックスがあることを確認し、グループ化と並べ替えを行い、エイリアス化された「CLIENT_NAME」からSQLテーブルの実際の列に並べ替えて、インデックスと一致するようにします

( Date_Added, Client_ID, Name)

「名前」は予約語でもあり、キーワードではなく列を明確にするのに役立つため、目盛りに「名前」があります。

次に、WHERE 句です。インデックス付きの列名に関数を適用するときはいつでも、特に日付/時刻フィールドでは最大限に機能しません... where句を次のように変更することをお勧めします

'2012-01-01' と '2012-12-31 23:59:59' の間の WHERE MCI.Date_Added

したがって、BETWEEN 範囲は 1 年全体を示しており、インデックスをより有効に活用できます。

最後に、上記が役に立たない場合は、クエリを分割することを検討します。TAGS の GROUP_CONCACT インライン選択は、ちょっとキラーかもしれません。クライアントごとにグループ化するために、最初にすべての個別の要素を用意し、次にそれらの詳細を取得したい場合があります....のようなもの

select
      PQ.*,
      group_concat(...) tags
   from
      ( the entire primary part of the query ) as PQ
         Left join yourGroupConcatTableBasis on key columns
于 2013-10-10T09:53:09.103 に答える
0

select から where 句とすべての列を削除し、count を追加して、取得するレコード数を確認します。妥当な場合は、最大 10k と言って、次の手順を実行します。

  1. M_CLIENT_INFO に関連する選択列を戻します

  2. ネストされた「TAGS」を含めないでください

  3. すべての結合を削除します

  4. where句なしでクエリを実行し、徐々に結合を含めます

このようにして、タイムアウトがいつ発生したかがわかります。

于 2013-10-10T09:12:34.093 に答える