使用结果集缓存优化性能
启用结果集缓存后,专用 SQL 池会在用户数据库中自动缓存查询结果,供重复使用。 这样,后续的查询执行就能直接从持久性缓存中获取结果,因此无需重新计算。 结果集缓存提高了查询性能,并减少了计算资源的用量。 此外,使用缓存结果集的查询不会占用任何并发槽,因此不会计入现有的并发限制。 出于安全考虑,如果访问方用户的数据访问权限与创建缓存结果的用户相同,则访问方用户只能访问缓存的结果。 在数据库和会话级别,结果集缓存默认情况下为“关闭”。
注意
不应将结果集缓存与 DECRYPTBYKEY 结合使用。 如果必须使用此加密函数,请确保在执行时(在会话级别或数据库级别)禁用结果集缓存。
关键命令
不缓存哪些内容
对数据库启用结果集缓存后,在缓存填满之前将缓存所有查询的结果,但以下查询除外:
- 带有内置函数或运行时表达式的查询,这些表达式为非确定性表达式,即使基表的数据或查询中没有更改。 例如,DateTime.Now()、GetDate()。
- 使用用户定义的函数的查询
- 使用具有行级别安全性的表的查询
- 其返回数据中的行大小超过 64KB 的查询
- 返回大数据(>10GB)的查询
注意
- 某些非确定性函数和运行时表达式对相同数据的重复查询来说可以是确定性。 例如,ROW_NUMBER()。
- 如果查询结果集中的行顺序/序列对应用程序逻辑很重要,请在查询中使用 ORDER BY。
- 如果 ORDER BY 列中的数据不是独一无二的,则无论是启用还是禁用结果集缓存,都不能保证 ORDER BY 列中值相同的行的行顺序。
重要
创建结果集缓存以及从缓存中检索数据的操作在专用 SQL 池实例的控制节点上进行。 当结果集缓存处于打开状态时,运行返回大型结果集(例如,>1GB)的查询可能会导致控制节点上带宽限制较高,并降低实例上的整体查询响应速度。 这些查询通常在数据浏览或 ETL 操作过程中使用。 若要避免对控制节点造成压力并导致性能问题,用户应在运行此类查询之前关闭数据库的结果集缓存。
此查询的运行持续时间以针对某个查询执行结果集缓存操作所需的时间为宜:
SELECT step_index, operation_type, location_type, status, total_elapsed_time, command
FROM sys.dm_pdw_request_steps
WHERE request_id = <'request_id'>;
下面是在禁用结果集缓存的情况上执行的某个查询的示例输出。
下面是在启用结果集缓存的情况上执行的某个查询的示例输出。
何时使用缓存结果
如果满足以下所有要求,则会对查询重复使用缓存结果集:
- 运行查询的用户有权访问该查询中引用的所有表。
- 新查询与生成结果集缓存的前一查询之间完全匹配。
- 从中生成缓存结果集的表中未发生任何数据或架构更改。
运行以下命令可以检查某个查询是否已执行并出现结果缓存命中或未命中情况。 result_cache_hit 列对缓存命中返回 1,对缓存失误返回 0,而对未使用结果集缓存的原因,则返回负值。 有关详细信息,请检查 sys.dm_pdw_exec_requests。
SELECT request_id, command, result_cache_hit FROM sys.dm_pdw_exec_requests
WHERE request_id = <'Your_Query_Request_ID'>
管理缓存结果
每个数据库的结果集缓存最大大小为 1 TB。 当基础查询数据更改时,缓存的结果将自动失效。
缓存逐出由专用 SQL 池按照以下计划自动管理:
- 尚未使用结果集或已失效(每 48 小时执行一次)。
- 当结果集缓存接近最大大小时。
用户可以使用以下选项之一手动清空整个结果集缓存:
- 对数据库禁用结果集缓存功能
- 连接到数据库后运行 DBCC DROPRESULTSETCACHE
暂停数据库不会清空缓存结果集。
后续步骤
有关更多开发技巧,请参阅 开发概述。