2016-12-14 8 views
1

私は、1日の合計カウント、 の合計がテーブルとその日付の合計で3つの列を持つレポートテーブルを作成しています。ここでMySQLのリクエストでテーブルを結合する方法を避ける方法

は、テーブルのスキーマです:

CREATE TABLE IF NOT EXISTS `partners_scanstracking` (
`pt_id` int(11) NOT NULL AUTO_INCREMENT, 
`pt_partner_id` int(5) NOT NULL, 
`pt_ip` varchar(30) NOT NULL, 
`pt_scanid` varchar(50) NOT NULL, 
`pt_fn` varchar(20) DEFAULT NULL, 
`pt_url` mediumtext, 
`pt_created` datetime NOT NULL, 
PRIMARY KEY (`pt_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0; 

そして、ここでは、私が作成したリクエストです:

SELECT COUNT(DISTINCT `c`.`pt_created`) AS `count`, 
     COUNT(DISTINCT `x`.`pt_scanid`) AS `uniq`, 
     `c`.`pt_created` 
FROM `partners_scanstracking` c 
LEFT JOIN 
    (SELECT `x`.* 
    FROM 
    (SELECT * 
     FROM `partners_scanstracking` 
     WHERE `pt_partner_id` = '0' 
     ORDER BY `pt_created` ASC) x 
    GROUP BY `pt_scanid`) x ON DATE(`c`.`pt_created`)=DATE(`x`.`pt_created`) 
WHERE (DATE(`c`.`pt_created`) >= '2016-10-06' 
     AND DATE(`c`.`pt_created`) <= '2016-12-14') 
    AND `c`.`pt_partner_id` = '0' 
GROUP BY DATE(`c`.`pt_created`) 
ORDER BY `c`.`pt_created` ASC 

Explain

すべてが前に素晴らしい仕事をしていたが、今の表では、500.000を持っていますレコードやリクエストが遅すぎる。私は主な理由は、私が2つの大きなテーブルに加わることだと思います。

クエリを最適化する方法やここでの参加を避ける方法がわかりません。

誰かが私を助けることができますか?

PS:最適化するものがない場合、計算結果のテーブルを作成してcrons scheduleを使用する必要があると思います。

+1

参加することを主な理由は、あなたがまたの出力を含める必要がありますインデックスを使用していけないように見えるのでとても遅い '[your_query]'ここ –

+2

'BY GROUP'で使用すべきではありません '* SELECT EXPLAIN '。考えてみてください...集計されていない集計キーではない列が返されます。 –

+0

Iveはpt_createdのインデックスとクエリの添付された説明を追加しました – Rooleek

答えて

1
  1. 必要のないフィールドは選択しないでください。 MySQL はサブクエリのSELECT *を無視するほどスマートであるかもしれませんが、私はそれに賭けません。
  2. 条件に関数呼び出しを使用しないでください。 pt_createdが索引付けされている場合、DATE()は索引を無視します。 pt_createdが索引付けされていない場合は、それが必要です。

    (DATE(c.pt_created)> = '2016年10月6日' AND DATE(c.pt_created)< = '2016年12月14日')

は、より良いよりなり

c.pt_created BETWEEN '2016-10-06 00:00:00' AND '2016-12-14 23:59:59' 

関連して、それがこれを行うことになっているものは非常にはっきりしていない:

ON DATE(`c`.`pt_created`)=DATE(`x`.`pt_created`) 

として効率的

このようなものではなく、そのクエリに何が必要なのでしょうか?

SELECT COUNT(DISTINCT `pst`.`pt_created`) AS `count`, 
     COUNT(DISTINCT `pst`.`pt_scanid`) AS `uniq`, 
     DATE(`c`.`pt_created`) AS theDate 
FROM `partners_scanstracking` AS pst 
WHERE pst.pt_created BETWEEN '2016-10-06 00:00:00' AND '2016-12-14 23:59:59' 
    AND pst.`pt_partner_id` = '0' 
GROUP BY theDate 
ORDER BY theDate ASC 
+0

一日ごとにユニークな 'pt_scanid'のセットに参加してから、私はそれらを数えてグループ毎に集計します – Rooleek

+0

COUNT(DISTINCT' pst'.'pt_scanid')AS 'uniq' - これは**この日**の一意の 'pt_scanid'を返しますが、** whole **テーブルのためには' pt_scanid'を完全にunqiueする必要があります。 – Rooleek

+0

これを別のクエリで実行することをおすすめします。 – Uueerdo

関連する問題