SQL执行计划是基于架构还是数据或两者兼而有之?

时间:2011-01-24 21:10:21

标签: sql optimization indexing sql-execution-plan

我希望这个问题不是太明显......我已经找到了许多关于解释执行计划的好信息,但有一个问题我没有找到答案。

计划(更具体地说是相对CPU成本)是仅基于架构,还是基于数据库中当前的实际数据?

我尝试对我的产品数据库中需要索引的位置进行一些分析,但我正在使用我自己的测试系统,该系统没有接近该字段中的产品所具有的数据量。我看到一些奇怪的事情,例如在添加索引后估计的CPU成本实际上略微上升,我想知道这是因为我的数据集是如此之小。

我正在使用SQL Server 2005和Management Studio来执行计划

6 个答案:

答案 0 :(得分:4)

它将基于Schema和Data。 Schema告诉它哪些索引可用,Data告诉它哪个更好。

答案可能会在很小的程度上发生变化,具体取决于您使用的DBMS(您尚未说明),但它们都会根据索引维护统计信息,以了解索引是否有帮助。如果索引将1000行分成900个不同的值,则它是一个很好的索引。如果一个索引只为1000行产生3个不同的值,那么它实际上不是selective所以它不是很有用。

答案 1 :(得分:2)

SQL Server是100%基于成本的优化器。其他RDBMS优化器通常是基于成本和基于规则的混合,但无论好坏,SQL Server完全由成本驱动。基于规则的优化器可以说是,例如, FROM子句中的表的顺序决定了连接中的驱动表。 SQL Server中没有这样的规则。见SQL Statement Processing

  

SQL Server查询优化器是一个   基于成本的优化器。每个可能的   执行计划有相关的成本   就计算量而言   使用的资源。查询优化器   必须分析可能的计划和   选择最低的那个   估计费用。一些复杂的SELECT   陈述有数千种可能   执行计划。在这些情况下,   查询优化器不会全部分析   可能的组合。相反,它   使用复杂的算法来查找   有成本的执行计划   合理地接近最小值   可能的费用。

     

SQL Server查询优化器可以   不要只选择执行计划   资源成本最低;它   选择返回结果的计划   给用户带来合理的费用   资源并返回结果   最快的。例如,处理a   并行查询通常使用更多   资源比连续处理,   但更快地完成查询。该   SQL Server优化器将使用   并行执行计划返回   如果服务器上的负载将结果   不会受到不利影响。

     

查询优化器依赖于   它的分布统计   估计资源成本   不同的提取方法   来自表或索引的信息。   保留分布统计数据   列和索引。他们指出了   a中值的选择性   特定索引或列。对于   例如,在代表汽车的表格中,   许多汽车都有相同的制造商,   但每辆车都有独特的车辆   识别号码(VIN)。一个索引   在VIN上比选择性更强   制造商的索引。如果   索引统计不是最新的,   查询优化器可能无法做到最好   选择目前的状态   表。有关的更多信息   保持索引统计最新,请参阅   Using Statistics to Improve Query Performance

答案 2 :(得分:1)

架构和数据。

在构建查询计划时会考虑统计信息,使用它们来估计查询中每个步骤返回的行数(因为这可能会影响不同类型的连接的性能等)。

这方面的一个很好的例子就是它不会在非常小的表上使用索引,因为在这种情况下执行表扫描会更快。

答案 3 :(得分:1)

我不能代表所有RDBMS系统,但Postgres专门使用估计的表大小作为构建查询计划的努力的一部分。例如,如果一个表有两行,它可以为使用该表的JOIN部分选择顺序表扫描,而如果它有10000多行,它可以选择使用索引或散列扫描(如果有的话)这些都是可用的。)顺便说一下,过去可以通过加入VIEW而不是实际表来触发Postgres中的不良查询计划,因为VIEW没有估计的大小。

Postgres构建其查询计划的部分原因取决于其配置文件中的可调参数。有关Postgres如何构建其查询计划的更多信息可以在Postgres网站上找到。

答案 4 :(得分:0)

对于SQL Server,有许多因素会影响最终的执行计划。在基本层面上,统计数据扮演着非常重要的角色,但它们基于数据,但并不总是基于所有数据。统计数据也不总是最新的。创建或重建索引时,统计信息应基于FULL / 100%数据样本。但是,自动统计刷新的采样率远低于100%,因此可以采样实际上不代表大部分数据的范围。操作的估计行数也起作用,可以基于表中的行数或过滤操作的统计信息。因此,过时(或不完整)的统计信息可以导致优化器选择一个不太理想的计划,就像表中的几行可以使它完全忽略索引(这可能更有效)。

正如另一个答案中所提到的,数据越独特(即选择性),索引就越有用。但请记住,唯一有统计数据的保证列是索引的前导(或“最左侧”或“第一”)列。 SQL Server可以并且确实收集其他列的统计信息,甚至可以收集其他列的统计信息,但仅当设置了AutoCreateStatistics DB选项时(默认情况下是这样)。

此外,当这些字段在查询中时,外键的存在可以帮助优化器。

但问题中未考虑的一个方面是查询本身。稍微更改但仍返回相同结果的查询可能具有完全不同的执行计划。也可以使用以下方法使索引的使用无效:

LIKE '%' + field

或将字段包装在函数中,例如:

WHERE DATEADD(DAY, -1, field) <  GETDATE()

现在,请记住,使用索引可以(理想情况下)读取操作更快,但DML操作(INSERT,UPDATE和DELETE)更慢(占用更多CPU和磁盘I / O),因为需要维护索引。 / p>

最后,并不总是依赖于“估计的”CPU等成本值。更好的测试是:

SET STATISTICS IO ON
run query
SET STATISTICS IO OFF

并专注于“逻辑读取”。如果减少逻辑读取,则应该提高性能。

最终,您需要一组与您在Production中有所接近的数据,以便对索引和查询本身进行性能调整。

答案 5 :(得分:0)

Oracle细节:

所述成本实际上是一个估计的执行时间,但它是以一种有点神秘的度量单位给出的,它与块读取的估计时间有关。重要的是要意识到计算出的成本对运行时没有太大影响,除非优化器做出的每一个估计都是100%完美的(从来就不是这样)。

在决定可以对查询应用哪些转换/启发式时,优化程序会使用架构执行许多操作。在评估xplans时,一些重要的模式事例:

  • 外键约束(可用于表消除)
  • 分区(排除整个数据范围)
  • 唯一约束(例如索引唯一与范围扫描)
  • 非空约束(在可为空的列上没有()中的反连接不可用
  • 数据类型(类型转换,专用日期算术)
  • 物化视图(用于重写针对聚合的查询)
  • 维度层次结构(用于确定功能依赖性)
  • 检查约束(如果降低成本则注入约束)
  • 索引类型(b-tree(?),位图,已加入,基于函数)
  • 索引中的列顺序({a,b}上的a = 1 =范围扫描,{b,a} =跳过扫描或FFS)

估算的核心来自使用收集的实际数据(或熟)数据。收集表,列,索引,分区以及其他可能的其他内容的统计信息。

收集以下信息:

  • 表/分区中的行数
  • 平均行/列长度(对于完全扫描,散列连接,排序,临时表的成本计算很重要)
  • col中的空值数(is_president ='Y'非常独特)
  • col中的不同值(last_name不是很独特)
  • col中的最小值/最大值(帮助无限范围条件,如date > x

...帮助估算过滤数据时返回的预期行/字节数。此信息用于确定哪些访问路径和连接机制可用且适合给定SQL查询的实际值与统计信息相比。

除此之外,还有物理行顺序会影响索引与全表扫描的“好”或吸引力。对于索引,这称为“聚类因子”,它是行顺序与索引条目顺序匹配程度的度量。