【发布时间】:2017-12-12 23:14:37
【问题描述】:
我正在使用Amazon Redshift。
我有一个 IP 地址列表。可能有来自同一个 IP 地址的多个条目,但在某个时间窗口内(例如 15 分钟)具有不同的 session_id。我想在这个时间窗口内计算任何给定 IP 地址的这些会话。
换句话说,我想知道在任何 15 分钟时间窗口内从某个 IP 地址登录的会话数。
所以我想出了以下查询:
SELECT t1.client_ip,
COUNT(DISTINCT t2.session_id) AS sessions
FROM t AS t1
JOIN t AS t2
ON t1.client_ip = t2.client_ip
AND t2.created_at BETWEEN t1.created_at
AND dateadd (MINUTE,15,t1.created_at)
GROUP BY t1.client_ip
HAVING COUNT(DISTINCT t2.session_id) >= 5
ORDER BY t1.client_ip
很遗憾,查询耗时过长,而且返回的结果也不正确。必须有更好的方法来实现这一点。表中有大约 1800 万个不同的 IP 地址,而表本身有大约 4 亿多条记录。
以下是一些示例数据:
Client_ip Session_id created_at
1.0.0.0 abc <timestamp>
1.0.0.0 def <timestamp> + 5 minutes
1.0.0.0 ghi <timestamp> + 25 minutes
2.0.0.0 jkl <timestamp1>
2.0.0.0 mno <timestamp1> + 10 minutes
2.0.0.0 pqr <timestamp1> + 20 minutes
要求的结果:
Client_ip #Sessions
1.0.0.0 2 (sessions abc and def)
2.0.0.0 2 (sessions mno and pqr)
任何帮助将不胜感激。
编辑:
也许问题不是很清楚。对此我深表歉意。
我不希望有一个固定的时间窗口,我可以在其中创建相隔 15 分钟的时间间隔。我想从某个 IP 地址计算任何 15 分钟窗口中的会话数。
例如:在我发布的示例数据中,会话mno 和pqr 应该被计算在内(对于它们的 IP 地址),因为它们彼此相距不到 15 分钟。同样,会话abc 和def 也应计入它们各自的 IP 地址,因为它们彼此相距不到 15 分钟。我没有为它创建外部开始时间。理想情况下,查询应将具有相同 IP 地址的每条记录与所有其他记录进行比较。不需要创建外部开始时间。
这是explain <query>的输出
XN Subquery Scan derived_table1 (cost=6516525010733.39..6516525010733.41 rows=2 width=524)
-> XN Merge (cost=6516525010733.39..6516525010733.39 rows=2 width=1032)
Merge Key: t1.client_ip
-> XN Network (cost=6516525010733.39..6516525010733.39 rows=2 width=1032)
Send to leader
-> XN Sort (cost=6516525010733.39..6516525010733.39 rows=2 width=1032)
Sort Key: t1.client_ip
-> XN HashAggregate (cost=5516525010733.36..5516525010733.38 rows=2 width=1032)
Filter: (count(DISTINCT session_id) >= 10)
-> XN Hash Join DS_DIST_BOTH (cost=6284418.61..5516506756947.79 rows=2433838076 width=1032)
Outer Dist Key: t2.client_ip
Inner Dist Key: t1.client_ip
Hash Cond: (("outer".client_ip)::text = ("inner".client_ip)::text)
Join Filter: (("inner".created_at <= "outer".created_at) AND ("outer".created_at <= date_add('minute'::text, 15::bigint, "inner".created_at)))
-> XN Seq Scan on fbs_page_view_staging t2 (cost=0.00..6279185.96 rows=2093062 width=1040)
Filter: ((created_at <= '2017-09-30 00:00:00'::timestamp without time zone) AND (created_at >= '2017-09-01 00:00:00'::timestamp without time zone))
-> XN Hash (cost=6279185.96..6279185.96 rows=2093062 width=524)
-> XN Seq Scan on fbs_page_view_staging t1 (cost=0.00..6279185.96 rows=2093062 width=524)
Filter: ((created_at <= '2017-09-30 00:00:00'::timestamp without time zone) AND (created_at >= '2017-09-01 00:00:00'::timestamp without time zone))
----- Tables missing statistics: fbs_page_view_staging -----
----- Update statistics by running the ANALYZE command on these tables -----
【问题讨论】:
-
您可以尝试使用子查询先获取所有行吗?喜欢 (SELECT * FROM t WHERE created_at BETWEEN now -15 and now) 并将其用于您的计算。
-
@clinomaniac 非常感谢您的回复。如果我有一个可以依赖的
start_date,那就太好了。在这种情况下,start_date正在滚动。我正在寻找任何 15 分钟时间范围内的会话数。 -
你的表格是由
client_ip分配并按(client_ip, created_at)排序的吗? -
任何查询优化问题都应包含查询中每个表的
SHOW CREATE TABLE <tablename>的输出,以及您查询的EXPLAIN <query>的输出。 -
为问题添加了更多详细信息。
标签: mysql sql amazon-redshift