有没有更有效的方法来编写这个 SQL 查询?
Is there a more efficient way to write this SQL query?
我有一个 table,里面有几百万条记录,它按 SessionGUID(访客)存储产品视图,table 结构是:
ID(PK)
SessionGUID(唯一标识符)
产品编号(整数)
日期时间(日期时间)
查询的目的是 return 由查看特定产品 ID 的同一个人查看的产品 ID 列表(即,查看 X 的客户也查看了 Y)
我使用的查询如下:
SELECT
A.ProductID
FROM
VISITOR_SESSIONS_PRODUCTVIEWS A
WHERE
A.SessionGUID IN (SELECT DISTINCT SessionGUID FROM VISITOR_SESSIONS_PRODUCTVIEWS WHERE ProductID = @ProductID)
GROUP BY
A.ProductID
ORDER BY
COUNT(A.ProductID) DESC
是否有更有效的方法来使用 GROUP BY/HAVING/PARTITON 或其他更优化的方法来按照我需要的方式获取数据?
我在我的开发服务器上是 运行 SQL 2008,但在 SQL Azure 上线时将是 运行。
通常,EXISTS
比 IN
更有效:
SELECT A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
WHERE EXISTS (SELECT 1
FROM VISITOR_SESSIONS_PRODUCTVIEWS B
WHERE B.ProductID = @ProductID AND
A.SessionGUID = B.SessionGUID
)
GROUP BY A.ProductID
ORDER BY COUNT(A.ProductID) DESC;
为了获得最佳性能,您需要 VISITOR_SESSIONS_PRODUCTVIEWS(SessionGUID, ProductId)
上的索引,也许还需要 VISITOR_SESSIONS_PRODUCTVIEWS(ProductId)
.
上的索引
编辑:
您可以尝试 使用window 函数编写此代码,但我不确定性能是否会更好:
select productid
from (select pv.*,
sum(case when productid = @productid then 1 else 0 end) over (partition by SessionGUID) as cnt
from visitor_sessions_productviews
) pv
where cnt > 0
group by productid
order by count(*) desc;
我不确定性能是否会比 EXISTS
方法更好。
有几种不同的编写方式可能会表现更好:
- 临时 Table 会话,然后加入 VISITOR_SESSIONS_PRODUCTVIEWS 这些会话
- 使用产品加入 VISITOR_SESSIONS_PRODUCTVIEWS 的会话,然后使用这些会话重新加入 VISITOR_SESSIONS_PRODUCTVIEWS
- EXISTS 而不是 DISTINCT 查询该用户会话的相关产品是否存在
这是临时 table 解决方案:
SELECT DISTINCT SessionGUID
INTO #sessionsWithProduct
FROM VISITOR_SESSIONS_PRODUCTVIEWS
WHERE ProductID = @ProductID;
SELECT
A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
INNER JOIN #sessionsWithProduct S ON s.SessionGUID = A.SessionGUID
GROUP BY A.ProductID
ORDER BY COUNT(A.ProductID) DESC;
DROP TABLE #sessionsWithProduct;
另外极其重要的是确保此 table 在 ProductID 和 SessionGUID 上 至少 编入索引(每个).
SELECT A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
JOIN VISITOR_SESSIONS_PRODUCTVIEWS S
ON A.SessionGUID = S.SessionGUID
AND S.ProductID = @ProductID
GROUP B A.ProductID
ORDER BY COUNT(DISTINCT(A.ProductID)) DESC
我有一个 table,里面有几百万条记录,它按 SessionGUID(访客)存储产品视图,table 结构是:
ID(PK) SessionGUID(唯一标识符) 产品编号(整数) 日期时间(日期时间)
查询的目的是 return 由查看特定产品 ID 的同一个人查看的产品 ID 列表(即,查看 X 的客户也查看了 Y)
我使用的查询如下:
SELECT
A.ProductID
FROM
VISITOR_SESSIONS_PRODUCTVIEWS A
WHERE
A.SessionGUID IN (SELECT DISTINCT SessionGUID FROM VISITOR_SESSIONS_PRODUCTVIEWS WHERE ProductID = @ProductID)
GROUP BY
A.ProductID
ORDER BY
COUNT(A.ProductID) DESC
是否有更有效的方法来使用 GROUP BY/HAVING/PARTITON 或其他更优化的方法来按照我需要的方式获取数据?
我在我的开发服务器上是 运行 SQL 2008,但在 SQL Azure 上线时将是 运行。
通常,EXISTS
比 IN
更有效:
SELECT A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
WHERE EXISTS (SELECT 1
FROM VISITOR_SESSIONS_PRODUCTVIEWS B
WHERE B.ProductID = @ProductID AND
A.SessionGUID = B.SessionGUID
)
GROUP BY A.ProductID
ORDER BY COUNT(A.ProductID) DESC;
为了获得最佳性能,您需要 VISITOR_SESSIONS_PRODUCTVIEWS(SessionGUID, ProductId)
上的索引,也许还需要 VISITOR_SESSIONS_PRODUCTVIEWS(ProductId)
.
编辑:
您可以尝试 使用window 函数编写此代码,但我不确定性能是否会更好:
select productid
from (select pv.*,
sum(case when productid = @productid then 1 else 0 end) over (partition by SessionGUID) as cnt
from visitor_sessions_productviews
) pv
where cnt > 0
group by productid
order by count(*) desc;
我不确定性能是否会比 EXISTS
方法更好。
有几种不同的编写方式可能会表现更好:
- 临时 Table 会话,然后加入 VISITOR_SESSIONS_PRODUCTVIEWS 这些会话
- 使用产品加入 VISITOR_SESSIONS_PRODUCTVIEWS 的会话,然后使用这些会话重新加入 VISITOR_SESSIONS_PRODUCTVIEWS
- EXISTS 而不是 DISTINCT 查询该用户会话的相关产品是否存在
这是临时 table 解决方案:
SELECT DISTINCT SessionGUID
INTO #sessionsWithProduct
FROM VISITOR_SESSIONS_PRODUCTVIEWS
WHERE ProductID = @ProductID;
SELECT
A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
INNER JOIN #sessionsWithProduct S ON s.SessionGUID = A.SessionGUID
GROUP BY A.ProductID
ORDER BY COUNT(A.ProductID) DESC;
DROP TABLE #sessionsWithProduct;
另外极其重要的是确保此 table 在 ProductID 和 SessionGUID 上 至少 编入索引(每个).
SELECT A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
JOIN VISITOR_SESSIONS_PRODUCTVIEWS S
ON A.SessionGUID = S.SessionGUID
AND S.ProductID = @ProductID
GROUP B A.ProductID
ORDER BY COUNT(DISTINCT(A.ProductID)) DESC