小编Yan*_*ton的帖子

键之间基数差异较大的表的基数估计

语境

我偶然发现了 SQL Azure 中的一个问题,其中Sort-operator 由于行估计不佳而溢出到 TempDB 中。

  • 我们正在查询与多个明细表连接的主表
  • 该表使用TenantId-column 对每个租户的表进行分区
  • 有些租户有 10,000 行,有些只有 100 行。
  • 有一个行级安全策略,可以为FILTER PREDICATE上述所有查询添加一个TenantId
  • 查询由 .NET 应用程序中的实体框架生成
  • 所有索引统计数据都是最新的
  • 所有明细表行都通过Index Seeks检索

问题

由于租户之间的行数差异很大,基数估计器产生的估计值非常低。这与两个内部连接相结合,进一步减少了估计,使得实际产生 3600 行的查询预计只产生 3。这是 3 个数量级的下降。

我尝试了什么?

  1. Filtered Statistics为那些产生大量行的键值定义,作为对 CE 的额外提示。
  2. 在处理参数化查询时遇到了限制。这OPTION ( RECOMPILE )适用于某些谓词,但不适用于TenantId通过上述安全策略注入的谓词。
  3. 内联过滤器谓词,因此我们在同一列上有效过滤两次有效,但似乎......至少可以说是多余的
  4. INNER JOINs更改为s 可以LEFT OUTER JOIN改善错误连接估计,但由于我们使用实体框架,我更喜欢不需要更改查询的解决方案。注意:显然,如果唯一的方法是重写查询,那么这就是我们将要走的路线。

其他想法

  • 我曾考虑过添加一个包含 10 万条记录的虚拟租户来抵消估计值的想法,这样行估计值至少对于最大的真实租户来说足够大,但这会使我们对小租户的估计过高。

我在寻找什么?

  • 我做错了什么 - 我把自己画到了一个角落里吗?
  • 有没有我可以考虑的替代方案?

我欢迎您的任何想法,谢谢!


排序运算符用于分页。我实际上不想检索所有行。所以简而言之,排序需要发生在数据库中(而不是在应用程序中)。

另外,要明确的是,这里的问题不是 EF 生成的查询。这是一个简单的查询,带有许多INNER/ …

sql-server statistics azure-sql-database cardinality-estimates

10
推荐指数
1
解决办法
540
查看次数