2010-12-07 20 views
7

私は例えば自分自身で実行すると、多くのentity_idクエリは時間がかかり始めると長いため、私はこれを行っておりますときに、非常に速いですが、以下の(ループは、PHPのforeachである)このクエリを持っていますループ内の別のエンティティで同じクエリを実行すると最大2.1秒かかります。クエリはループ内に置かれるエンティティの方が遅くなり、処理速度が遅くなるようです。どうしてこれなの?どのようにクエリを改善/最適化できますか?mysqlのクエリ速度最適化

foreach($entity_ids as $entity_id) { 
    SELECT COUNT(*) as prev, DATE_FORMAT(`created`, '%Y%m%d') AS date_group 
    FROM articles_entities 
    WHERE entity_id = '$entity_id' 
    AND `created` >= DATE_SUB(CURDATE(), INTERVAL 10 DAY) 
    GROUP BY date_group 

    // store result 
} 

私は、次の表の構造を持っている:

CREATE TABLE `articles_entities` (
    `id` CHAR(36) NOT NULL, 
    `article_id` CHAR(36) NOT NULL, 
    `entity_id` CHAR(36) NOT NULL, 
    `created` DATETIME DEFAULT NULL, 
    `modified` DATETIME DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `article_id` (`article_id`), 
    KEY `entity_id` (`entity_id`), 
    KEY `created` (`created`) 
) ENGINE=MYISAM DEFAULT CHARSET=utf8; 

答えて

7

IDの配列を持っているように見えますが、IDフィールドが配列の値の1つと一致するテーブルからレコードを引き出したいと思っています。

PHPでLOOPを使用して複数のSQL文を実行するのではなく、1つのマスター文を作成してからPHPを使用して結果を処理するのが最適です。あなたは、SQL IN文を使用してこれを実現することができます

// where $entity_ids is an array eg 1,2,3,4,5 

    $sql="SELECT entity_id AS 'alt_entity_id', COUNT(entity_id) as prev, DATE_FORMAT(`created`, '%Y%m%d') AS 'date_group' 
    FROM articles_entities 
    WHERE entity_id IN ".implode(",",$entity_ids)." 
    AND `created` >= DATE_SUB(CURDATE(), INTERVAL 10 DAY) 
    GROUP BY date_group, entity_id"; 
    // you may wish to revese the group fields, as you require, you may also wish to change the count field to date_group, depending on what you wish to be counted 

これは、日付と渡されたid値の両方でグループ化され、あなたが持っているすべてのID値のため、元のクエリを一度に実行されます。その後、PHPを使用して、返された結果セットから特定のIDの結果を除外することができます。

これは、クエリの実行をループすることによって生成されるオーバーヘッドよりはるかに効率的です。

entity_id | count(entity_id) | date_group 
----------|------------------|------------ 
    1  |  3   | 2010-04-01 
    1  |  3   | 2010-03-01 
    1  |  3   | 2010-02-01 
    2  |  2   | 2010-01-01 
    2  |  2   | 2010-02-01 
    3  |  1   | 2010-06-01 
    4  |  2   | 2010-06-01 
    4  |  2   | 2010-02-01 
+0

答えに欠けているものは、entity_idをalt_entity_idとして選択していましたが、どちらのエンティティを選ぶことができましたか(誤った結果を与えたのでentity_idだけを選択できませんでした。私もグループ分けを交換しなければなりません。あなたの答えを更新するなら、私はそれを受け入れます。 – Lizard

+0

うれしいことですが、私は更新しましたd :) – SW4

2

私はあなたのループの実体値を取得している場所がわからないが、ループ内でこのクエリを実行すると、常になります大きなパフォーマンスオーバーヘッド。以前のSQLクエリからentity_idを取得している場合は、最初のクエリをループクエリと結合するようにSQLをリファクタリングして、必要なすべてのデータを1つのSQLクエリで返すようにしてください。

+0

私は$ entity_idsから来るんPHPのループ – Lizard

+0

を追加しました:

あなた返された結果は次のようになりますか? –

+0

特定の基準(異なる日付範囲)に一致する同じテーブルの記事を最初に選択し、エンティティ – Lizard

0

大雑把にあなたがどのように多くのエンティティを扱っていますか?複数のクエリを持っているのではなく、

あなたは別々のテーブルに必要なentitesを挿入でき、参加していますか?

0

文字列を形成するために、それに参加し、配列にすべてのIDを取り、「どこで」、その後

SELECT COUNT(*) as prev, DATE_FORMAT(`created`, '%Y%m%d') AS date_group 
    FROM articles_entities 
    WHERE entity_id in (".$entityIDString.") 
    AND `created` >= DATE_SUB(CURDATE(), INTERVAL 10 DAY) 
    GROUP BY date_group, entity_id 

最適な方法

を行う

$enitityIDS = array(); 
    foreach($entity_ids as $entity_id) { 
     $enitityIDS[]=$entity_id; 
    } 
    $entityIDString = join(",",$enitityIDS); 

最適化された方法で、詳細情報を取得するために使用

+1

idフィールドの場合、IN句の結果は区別できません – SW4