表分区的阴暗面(执行计划)

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

CareSon 发表了一片博文http://www.cnblogs.com/CareySon/archive/2012/10/30/2745918.html其实我碰到过类似的事情,但是没有仔细研究为什么。借着CareSon的Demo,仔细的观察了执行计划。

测试数据

  当然第一步根据CareSon的Demo建立一份测试数据。

  第二步为了做比较的需要,建一个非分区的非聚集索引,Key 和 分区对齐的非聚集索引一样。

  第三步建议一个非分区表,数据和分区表一样,我在测试的时候叫Order2

  第四步在Order2建3个索引,1 聚集索引非分区,2.非聚集索引分区,3非聚集索引非分区

疑问

  这样测试数据就准备全了。CareSon的博文给我几个问题:1.为啥不走非聚集索引,2.走了索引会怎么样,3如果索引是非分区索引呢,4如果表是非分区表,中的分区索引会怎么样

测试结果

  根据问题我写了一下几个sql和对应执行计划和结果(性能差距很大所以单看执行计划就能猜出那个性能比较好):

  1.使用索引提示,强行走分区索引

SELECT TOP 100 id,OrderDate,DateModified,Placeholder 
FROM dbo.Orders WITH (INDEX = IDX_Data_DateModified_Id_OrderDate)
WHERE DateModified >='20120625'
ORDER BY DateModified,Id

  

  

(100 行受影响)
表 'Orders'。扫描计数 4,逻辑读取 286265 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

SQL Server 执行时间:
CPU 时间 = 1514 毫秒,占用时间 = 1132 毫秒。

  2.在分区表中不走索引(在这里表结构要稍微的变动一下,把非聚集索引删除)

SELECT TOP 100 id,OrderDate,DateModified,Placeholder 
FROM dbo.Orders 
WHERE DateModified >='20120625'                          
ORDER BY DateModified,Id

  

(100 行受影响)
表 'Orders'。扫描计数 6,逻辑读取 25229 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

SQL Server 执行时间:
CPU 时间 = 266 毫秒,占用时间 = 513 毫秒。

  3.使用索引提示,强行走非分区索引

SELECT TOP 100 id,OrderDate,DateModified,Placeholder FROM 
dbo.Orders WITH (INDEX = idx_DateModified)
WHERE DateModified >='20120625' 
ORDER BY DateModified,Id

  

  

(100 行受影响)
表 'Orders'。扫描计数 1,逻辑读取 318 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 122 毫秒。

  4.在非分区表中,使用索引提示走分区索引

SELECT TOP 100 id,OrderDate,DateModified,Placeholder 
FROM dbo.Orders2 with (INDEX = IDX_Data2p_DateModified_Id_OrderDate)
WHERE DateModified >='20120625'
ORDER BY DateModified,Id

  

(100 行受影响)
表 'orders2'。扫描计数 4,逻辑读取 286265 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

SQL Server 执行时间:
CPU 时间 = 1701 毫秒,占用时间 = 1152 毫秒。

  5.非分区表正常运行

SELECT TOP 100 id,OrderDate,DateModified,Placeholder 
FROM dbo.Orders2 
WHERE DateModified >='20120625'
ORDER BY DateModified,Id

(100 行受影响)
表 'orders2'。扫描计数 1,逻辑读取 318 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

(1 行受影响)

SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 140 毫秒。

解决问题

  现在结果有了,那么就来解答先前的几个问题1.为啥不走非聚集索引,2.走了索引会怎么样,3如果索引是非分区索引呢,4如果表是非分区表,中的分区索引会怎么样

  1.为啥不走索引呢?

    1和2 对比一下,1中逻辑读大概是2中的10倍,就算SQL Server 再傻也会用2这个执行计划。

  2.走了索引会怎么样?

    看1的执行时间和执行计划,走了索引性能很烂

  3.如果索引是非分区索引呢?

    请对比1和3,2和3性能差距不是一点点,那么就引出另外一个话题,为什么非分区索引性能比分区的好呢?这个下面再讨论

  4.表如果是非分区表,中的分区索引会怎么样?

    对比4和5非常负责任的告诉你,性能很烂。

总结

  现在来说说为什么非分区索引性能在这里比分区的好,分区索引是根据分区方案,分别存放,如前面的例子直接使用某个值来过滤,索引查找会扫描所有分区,查询那些数据,那么它读取的页远远大于直接在非聚集索引中seek,自己运行demo,查看非聚集索引seek左边的排序,是根据orderdate,id排序,视乎在为了给嵌套循环做准备,之后还要根据datemodified,id排序。非分区索引严格按照排序的字段排序,因此看执行计划的时候看实际相应行数为100,但是看走分区索引的实际相应行数则为170081也就意味着走非分区索引加大了IO,和多余的计算。恰恰造成查询偏慢的原因就是因为分区的阴暗面。不恰当的使用分区。CareSon的博文让我对分区表和索引对齐有了更加深入的认识。



    本文转自 Fanr_Zh 博客园博客,原文链接:http://www.cnblogs.com/Amaranthus/archive/2012/11/12/2766101.html,如需转载请自行联系原作者




相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
8月前
|
存储 关系型数据库 MySQL
MySQL查询执行计划详解(EXPLAIN)
一、单表查询 访问方法/访问类型: • const:通过主键值或唯一二级索引与一个常熟进行等值查询(不包括NULL),只会生成一条记录 • ref:普通二级索引与一个常数进行等值比较,可能生成多条记录 • ref_or_null:ref的前提下可以加上or key is null • range:对应的扫描区间为若干个单点扫描区间或范围扫描区间(不包括负无穷到正无穷的范围) • index:扫描区间为全表,但是可以在二级索引中扫描(因为二级索引每条记录占用空间更小,所以需要读的页更少) • all:直接扫描全部的聚集索引记录
|
索引
索引下推
大家多多 关注
155 0
|
存储 关系型数据库 MySQL
索引及查询优化
索引及查询优化
70 0
|
NoSQL MongoDB 开发者
索引的使用 执行计划 | 学习笔记
快速学习 索引的使用 执行计划
索引的使用 执行计划 | 学习笔记
|
关系型数据库 MySQL
|
SQL 索引 存储
执行计划的生成
原文:执行计划的生成   SQL Server使用许多技术来优化资源消耗: 基于语法的查询优化; 无用计划匹配以避免对简单查询的深度优化; 根据当前分布统计的索引和连接策略; 多阶段的查询优化以控制优化开销; 执行计划缓冲以避免重新生成执行计划;   以上技术按以下顺序执行: 解析器; 代数化器; 查询优化器; 执行计划生成,缓冲和hash计划生成; 查询执行;   其执行顺序如下:    一、解析器(parser)   当查询被提交时,SQL Server将它传递给关系引擎中的解析器。
1142 0
|
SQL 测试技术 Go
|
SQL 数据库 索引