调整此查询的性能
Posted
技术标签:
【中文标题】调整此查询的性能【英文标题】:Performance tuning this query 【发布时间】:2020-11-06 19:22:30 【问题描述】:我有以下(简单)查询,大约需要 22 秒才能完成:
SELECT
c.city_name, c.task_name, COUNT(c.customer_id) AS customers,
ROUND(SUM(c.opportunitySize),2) AS opportunitySize
FROM
customeropp AS c
WHERE
account_id = '1000' AND campaign_cycle = 'm07a2020'
GROUP BY
c.city_name, c.task_name
ORDER BY
opportunitySize DESC
FOR JSON PATH
我的理解是索引可以提高速度所以我也添加了以下索引
CREATE NONCLUSTERED INDEX IX_campaign_and_account
ON customeropp (campaign_cycle, account_id) WITH (DROP_EXISTING = ON);
CREATE NONCLUSTERED INDEX IX_city_name
ON customeropp (city_name) WITH (DROP_EXISTING = ON);
CREATE NONCLUSTERED INDEX IX_task_name
ON customeropp (task_name) WITH (DROP_EXISTING = ON);
CREATE NONCLUSTERED INDEX IX_opportunitySize
ON customeropp (opportunitySize DESC) WITH (DROP_EXISTING = ON);
还有一些其他索引,但与此特定查询无关。
列类型如下:
目前使用的表大约有 300 万条记录,数据库在无服务器 Azure 数据库计划中运行(最多 40 个 vCore,最多 120 GB 内存)。
知道如何让这个运行得更快吗?
编辑:
执行计划见:https://www.brentozar.com/pastetheplan/?id=SkSt_mQKv
【问题讨论】:
能否请您将实际执行计划发布到brentozar.com/pastetheplan 执行计划是什么?查询不简单 - 将结果转换为 JSON 的成本很高。按 聚合 排序需要在排序之前计算和假脱机 tempdb 中的所有结果,这意味着没有任何索引可以用于加速排序操作 获取实际执行计划解释here。您可以在( account_id, campaign_cycle, city_name, task_name ) include ( customer_id, opportunitySize )
上尝试covering index。它按顺序处理where
和group by
子句,并提供select
和order by
子句所需的剩余数据。
@HABO 哇...随着您涵盖索引建议,查询现在不到 1 秒。感觉就像魔术!
【参考方案1】:
在索引定义中使用包含列
CREATE INDEX index_name
ON table_name(campaign_cycle, account_id)
INCLUDE(city_name, task_name, opportunitySize, customer_id );
【讨论】:
这个似乎提高了查询性能,但不如上面的@HABO建议 最好选择的列在包含的列中 @Mrsmiri 该索引主要提高where
子句(account_id
和campaign_cycle
)的性能,但它也可以通过以下方式提高group by (
city_name` 和task_name
)的性能对这些列进行排序。此时,唯一不在索引中的select
列是customer_id
和opportunitySize
。可以从表行中检索它们,但使用include
将它们添加到索引允许执行查询而根本不访问表行。理论上,至少。也许@JavierC 会将新的执行计划添加到帖子中,以便我们查看。
@HABO 这是新的执行计划brentozar.com/pastetheplan/?id=Byhv6IEFD以上是关于调整此查询的性能的主要内容,如果未能解决你的问题,请参考以下文章