次のような Web サイトのページ ビューを含むテーブルがあります。
time | page_id
----------|-----------------------------
1256645862| pageA
1256645889| pageB
1256647199| pageA
1256647198| pageA
1256647300| pageB
1257863235| pageA
1257863236| pageC
本番テーブルには、現在約 40K 行あります。過去 30 日間、60 日間、および 90 日間に表示されたユニークページの数を日ごとに生成したいと考えています。したがって、結果セットで 1 日を調べて、その日までの 60 日間にアクセスされた一意のページの数を確認できます。
MSSQL で動作するクエリを取得できました。
SELECT DISTINCT
CONVERT(VARCHAR,P.NDATE,101) AS 'DATE',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE NDATE BETWEEN DATEADD(D,-29,P.NDATE) AND P.NDATE) AS SUB) AS '30D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE NDATE BETWEEN DATEADD(D,-59,P.NDATE) AND P.NDATE) AS SUB) AS '60D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE NDATE BETWEEN DATEADD(D,-89,P.NDATE) AND P.NDATE) AS SUB) AS '90D'
FROM PERFLOG P
ORDER BY 'DATE'
注: MSSQL には FROM_UNIXTIME 関数がないため、テスト用に NDATE 列を追加しました。これは単に変換されtime
た . NDATE は本番テーブルに存在しません。
このクエリを MySQL に変換すると、「不明な列 P.time」エラーが発生します。
SELECT DISTINCT
FROM_UNIXTIME(P.time,'%Y-%m-%d') AS 'DATE',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE FROM_UNIXTIME(time,'%Y-%m-%d') BETWEEN DATE_SUB(FROM_UNIXTIME(P.time,'%Y-%m-%d'), INTERVAL 30 DAY) AND FROM_UNIXTIME(P.time,'%Y-%m-%d')) AS SUB) AS '30D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE FROM_UNIXTIME(time,'%Y-%m-%d') BETWEEN DATE_SUB(FROM_UNIXTIME(P.time,'%Y-%m-%d'), INTERVAL 60 DAY) AND FROM_UNIXTIME(P.time,'%Y-%m-%d')) AS SUB) AS '60D',
(SELECT COUNT(DISTINCT SUB.PAGE_ID) FROM (SELECT PAGE_ID FROM perflog WHERE FROM_UNIXTIME(time,'%Y-%m-%d') BETWEEN DATE_SUB(FROM_UNIXTIME(P.time,'%Y-%m-%d'), INTERVAL 90 DAY) AND FROM_UNIXTIME(P.time,'%Y-%m-%d')) AS SUB) AS '90D'
FROM PERFLOG P
ORDER BY 'DATE'
これは、外側の FROM 句でテーブルを参照する相関サブクエリを使用できないためだと理解しています。しかし、残念ながら、このクエリを MySQL で機能するように変換する方法がわかりません。今のところ、テーブルからすべての DISTINCT 行を返し、それを PHP で後処理するだけです。40K 行の場合、約 2 ~ 3 秒かかります。数百から数千の行がある場合のパフォーマンスが心配です。
MySQLで行うことは可能ですか? もしそうなら、私たちのPHP後処理ソリューションよりも優れたパフォーマンスを期待できますか.
更新: テーブルを作成するためのクエリは次のとおりです。
CREATE TABLE `perflog` (
`user_id` VARBINARY( 40 ) NOT NULL ,
`elapsed` float UNSIGNED NOT NULL ,
`page_id` VARCHAR( 255 ) NOT NULL ,
`time` INT( 10 ) UNSIGNED NOT NULL ,
`ip` VARBINARY( 40 ) NOT NULL ,
`agent` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `user_id` , `page_id` , `time` , `ip`, `agent` )
) ENGINE MyISAM
私たちの本番テーブルには、これまでに最大 4 万行あります。