0
SELECT COUNT(organization.ID)
FROM organization
WHERE organization.NAME IN (
    SELECT organization.NAME
    FROM organization
    WHERE organization.NAME <> ''
        AND organization.APPROVED = 0 
        AND organization.CREATED_AT > '2012-07-31 04:31:08'
    GROUP BY organization.NAME
    HAVING COUNT(organization.ID) > 1
)

このクエリは重複を検出します。問題は、内部ステートメントが原因でページが読み込まれるまでに6秒かかることです。実行速度を上げる方法はありますか?MySQLデータベースバージョン5.1。

4

4 に答える 4

1

はい。MySQLは「in」クエリの処理が遅いため、これは遅いです。代わりにこれを使用して修正できます。

SELECT COUNT(organization.ID)
FROM organization o
WHERE exists (
    SELECT organization.NAME
    FROM organization o2
    WHERE organization.NAME <> ''
        AND organization.APPROVED = 0 
        AND organization.CREATED_AT > '2012-07-31 04:31:08' and
        organization.name = o.organization.name
    GROUP BY organization.NAME
    HAVING COUNT(organization.ID) > 1
)
于 2012-08-31T20:53:38.167 に答える
0

避けるようにしてくださいIN

SELECT COUNT(organization.ID)
FROM 
    organization
    INNER JOIN 
    (
        SELECT organization.NAME
        FROM organization
        WHERE organization.NAME <> ''
            AND organization.APPROVED = 0 
            AND organization.CREATED_AT > '2012-07-31 04:31:08'
        GROUP BY organization.NAME
        HAVING COUNT(organization.ID) > 1
    ) AS t ON organization.NAME = t.Name
于 2012-08-31T20:52:29.213 に答える
0

また、含まれているdbフィールドのインデックスを作成すると、複雑なクエリの速度が大幅に向上することもわかりました。

于 2012-08-31T20:58:01.143 に答える
0

返したいのがすべての重複の合計「カウント」であるが、APPROVEDとCREATED_ATに指定された述語を持つ2つ以上の行を持つ組織NAMESの場合のみ、代替ステートメントを使用して同等のものを返すことができます。結果:

SELECT SUM(c.cnt) 
  FROM ( SELECT COUNT(organization.ID) AS cnt
           FROM organization o
          WHERE o.NAME <> ''
          GROUP
             BY o.NAME
         HAVING SUM(o.APPROVED = 0 AND o.CREATED_AT > '2012-07-31 04:31:08') > 1
       ) c

MySQLは、このクエリを満たすために適切なカバーインデックスを利用できます。そうでない場合、これは組織テーブルのフルスキャンである可能性があります。ただし、組織テーブルを2回参照することは避け、JOIN操作を避けます。

このクエリに適したカバーインデックスの1つは、次のとおりです。

ON organization (NAME, CREATED_AT, APPROVED, ID)

列が非NULLであることが保証されている場合ID(NOT NULL制約またはテーブルの主キーのいずれかである場合は、その列の参照を回避でき、その列をインデックス定義から除外できます)。

SELECT SUM(c.cnt) 
  FROM ( SELECT SUM(1) AS cnt
           FROM organization o
          WHERE o.NAME <> ''
          GROUP
             BY o.NAME
         HAVING SUM(o.APPROVED = 0 AND o.CREATED_AT > '2012-07-31 04:31:08') > 1
       ) c

EXPLAIN出力は、インデックスを使用してこのクエリを表示し、テーブルのデータブロックを参照せずにクエリを満たします。

id  select_type  table       type    possible_keys    key              key_len  ref       rows  Extra                     
--  -----------  ----------  ------  ---------------  ---------------  -------  ------  ------  --------------------------
 1  PRIMARY      <derived2>  ALL     (NULL)           (NULL)           (NULL)   (NULL)       2                            
 2  DERIVED      o           index   organization_ix  organization_ix  44       (NULL)      29  Using where; Using index  
于 2012-08-31T21:23:58.507 に答える