如何解决如何优化此查询n+1 和dense_rank 之后
如何优化此查询
WITH stats AS (SELECT a.IntegratorSalesAssociateID,a.AgentName,(
SELECT COUNT(*)
FROM properties AS p
WHERE a.IntegratorSalesAssociateID = p.IntegratorSalesAssociateID
AND p.TransactionType = '2'
AND MONTH(p.OrigListingDate) = MONTH(CURRENT_DATE)
AND YEAR(p.OrigListingDate) = YEAR(CURRENT_DATE)
) AS properties_this_month
FROM agents AS a)
SELECT stats.*,DENSE_RANK() over (ORDER BY stats.properties_this_month DESC) AS 'rank'
from stats
我想也许如果我加入两个表并以某种方式对它们进行分组,它会表现得更好,目前它运行了 17.5 秒,奇怪的是,添加dense_rank 根本不会影响性能。
相关表结构
CREATE TABLE `agents`
(
`IntegratorSalesAssociateID` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL,`AgentName` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`created_at` timestamp NULL DEFAULT NULL,`updated_at` timestamp NULL DEFAULT NULL
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE `properties`
(
`id` bigint(20) UNSIGNED NOT NULL,`IntegratorSalesAssociateID` varchar(13) COLLATE utf8mb4_unicode_ci NOT NULL,`TransactionType` tinyint(4) NOT NULL,`OrigListingDate` date DEFAULT NULL,`updated_at` timestamp NULL DEFAULT NULL
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
解决方法
你可以试试这个:
;WITH stats AS
(
SELECT
p.IntegratorSalesAssociateID,COUNT(*) AS properties_this_month
FROM properties AS p
WHERE p.TransactionType = '2'
AND MONTH(p.OrigListingDate) = MONTH(CURRENT_DATE)
AND YEAR(p.OrigListingDate) = YEAR(CURRENT_DATE)
GROUP BY p.IntegratorSalesAssociateID
)
SELECT
a.IntegratorSalesAssociateID,a.AgentName,COALESCE(s.properties_this_month,0) AS properties_this_month
FROM agents AS a
LEFT JOIN stats s ON a.IntegratorSalesAssociateID = s.IntegratorSalesAssociateID
,
鉴于 DENSE_RANK()
不影响性能,您想要优化:
SELECT a.IntegratorSalesAssociateID,(SELECT COUNT(*)
FROM properties p
WHERE a.IntegratorSalesAssociateID = p.IntegratorSalesAssociateID AND
p.TransactionType = '2' AND
MONTH(p.OrigListingDate) = MONTH(CURRENT_DATE) AND
YEAR(p.OrigListingDate) = YEAR(CURRENT_DATE)
) AS properties_this_month
FROM agents a;
我会改写为:
SELECT a.IntegratorSalesAssociateID,(SELECT COUNT(*)
FROM properties p
WHERE a.IntegratorSalesAssociateID = p.IntegratorSalesAssociateID AND
p.TransactionType = 2 AND
p.OrigListingDate >= CURRENT_DATE - INTERVAL (1 - DAY(CURRENT_DATE) DAY
) AS properties_this_month
FROM agents a;
两个变化是:
-
TransactionType
看起来像一个数字。假设是这样,我删除了单引号。不要混合数据类型!当然,如果列是字符串,那就用单引号。 - 我更改了日期逻辑以删除列上的所有函数。我假设没有未来的“原始”日期。如果是这样,您可以为月底添加另一个条件。
然后,对于这个查询,您需要一个索引:properties(IntegratorSalesAssociateID,TransactionType,OrigListingDate)
。实际上,该索引可能适用于数据的原始版本。
我真诚地怀疑使用显式聚合会提高性能。 GROUP BY
——虽然非常强大——通常比相关子查询慢。并且使用正确的索引几乎总是变慢(或至少不会变快)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。