![]() |
1
2
从这些查询计划看来,您可以从这样的索引中获益(如果我正确推断了您的数据库架构):
一般来说,这似乎是一个标准的查询优化问题,而表值函数在这里并没有产生实际的影响。 |
![]() |
2
2
短期计划使用
HashJoin
和聚集索引扫描
如果没有关于所有相关因素的确切信息(使用的确切模式,包括每个索引,以及每个相关表的确切统计和基数),就不可能给出一个解决方案。一个简单的方法就是使用计划指南,参见 Designing and Implementing Plan Guides . |
![]() |
3
1
这里有几个部分的答案。在第一部分中,我将尝试回答一个问题(你没有问)为什么没有一个查询特别快。这和你实际上问的问题有关,所以请容忍我。
你的约会标准通常不是
SARGable
正如您所指定的--例如
在调用表中使用带有日期索引和调用I d的范围查询,在任何情况下都会大大提高性能,并降低查询对客户id选择性的敏感度。假设日期在调用表中,我将重写内部UDF,并调整输入参数以使用日期。这样做也会让你的乳房功能更加丰富:
你的另一个观点也是如此。通过使用year()和date_only()函数,可以使日期上的任何统计数据或索引都变得毫无用处(尽管优化器可以使用它们来限制扫描的数据量,但这是一个更大的讨论)。 那么——为什么你的乳房需要永远?因为它调用另一个UDF,而您使用date_only()作为连接参数,所以它几乎无法“知道”UDF子查询中的期望值,所以它选择了循环连接。它之所以选择该计划,很可能是因为它适合于customer_id的某些值。很可能是在创建UDF后不久,您就对这些选择性customer_id中的一个运行了查询,并且该查询的计划已被缓存,即使它不适合customer_id的其他值。 为什么一个存储过程不需要永远?因为第一次运行它时,存储过程根据您给出的第一个条件生成计划。也许第一次运行SP时,您使用了非选择性的客户ID,而存储的proc选择了散列连接。对于即席查询也是如此。优化器“注意到”您已经向它传递了一个非选择性的客户id,并选择为您创建一个散列连接。 不管怎样,除非你控制了日期的可搜索性问题,否则你会发现你的所有查询都会对你的客户id输入非常敏感,而且根据你的使用模式,它们可能会在你的脸上炸掉,不管你是不是udf。 希望这有帮助! |
![]() |
4
0
我在SQL Server 2005中看到过这种情况。当我们对特定查询使用表值函数时,我们确实获得了糟糕的性能。将查询、参数和所有内容的文本完全相同,放入一个存储过程中,可靠地得到了一个极好的查询计划。使用与存储过程相同的参数调用函数会产生不同的行为(我们都是从冷缓存开始的)。非常令人失望! 遗憾的是,我们没有时间更深入地诊断这种奇怪的行为,并在2005年推动了避免表值函数的项目。 这可能表示SQL Server 2005中存在错误。 |
![]() |
ybou · 需要帮助从SQL 2005查询中删除过时的=*连接运算符 7 年前 |
![]() |
Robert · 将多个分隔符分隔的字段视为不同的行 8 年前 |
![]() |
hud · 执行存储过程会导致错误 9 年前 |
![]() |
Gonzalo · 如何将存储过程的结果插入到新表中? 9 年前 |