日期:2014-05-17  浏览次数:20365 次

一个非常非常弱的问题:主键的排序


假设表中有20条记录,正常设置ID为主键,自增,+1

设置1:(默认)按照ASC升序
是不是理解为存储的时候按照1——20?

设置2:如果将主键改为DESC降序
存储的时候是不是20——1?

-----弱弱的分割线-----

查找第5条记录
设置1:查找20——6,不是,跳过,——5正确。
设置2:查找1——4,不对,跳过,——5正确。

是这个运行机制么……?
如果是的话,数据量很大的情况下,设置2要比设置1好?

B树结构,20条记录理解为20个页
那么设置2需要跳过的只是4个页
而设置1需要跳过15个页

-----弱弱的分割线-----

今天突然很2B地冒出这个想法,求解救!

------解决方案--------------------
设置1与设置2的排序存储应该就是你说的顺序

你举的查找例子不太恰当,按你的逻辑,当查询20的时候desc是不是就占优势了呢

既然你了解聚集索引是B树结构,或者说既然你有这样的疑问,应该先去了解一下索引查询的方式方法,当然这方面我了解的也不是很深,可以给你简单举个例子

比如1-20个数据,每个数据页存储5个,那么占用了4个数据页,如果你要查询10这条数据,索引是要先定位10这条数据所在的数据页,比如2页,然后再进入数据页中进行检索
------解决方案--------------------
按照楼主说的,是在逐个页面比较了,事实上在B树的遍历时,不存在你说的跳过的情况,叶子节点是通过上层节点的入口地址进入的,从根节点开始,就已经知道下个节点要往哪里去了。
这也是索引扫描 和 索引查找不一样的地方哦。

不过对于索引树的遍历ASC/DESC确实有他的意义,尤其当遇到联合索引时。
------解决方案--------------------
查找第5条记录
设置1:查找20——6,不是,跳过,——5正确。
设置2:查找1——4,不对,跳过,——5正确。

这个是局部扫描操作,Seek查找5是从根/中间级/叶级直接命中数据,Seek速度取决于树的深度,当然表越大越慢。

如果是范围查找比如7-15,取决于索引顺序,如果是DESC命中15开始向前局部扫描,如果是ASC则命中7开始向前局部扫描,索引顺序不会影响Scan/Seek的速度。

按照实际业务操作中,定义为DESC是有问题的,每条数据都是插入,假设每页2条数据,每次插入两条,就不考虑页拆分了:
2,1 <-> 4,3 <-> 6,5 <-> 8,7 <-> 10,9
进行局部扫描的时候,导致磁头疯狂的往返移动,比如查找4-8:8,7同一页中是向前的,下一页6,5物理位置和逻辑位置相反,磁头回撤。重建索引整理碎片之后的情形:
10,9 <-> 8,7 <-> 6,5 <-> 4,3 <-> 2,1


------解决方案--------------------
说一下个人感觉,不一定对。
索引分成聚集索引和非聚集索引。主键通常是聚集索引,也可能是非聚集索引。
假如有10000条记录,1000条记录一个叶子,就是有10个叶子。
如果要找3210这条记录,无论是ASC还是DESC,应该都是一样的速度找到3001-4000这个叶子。
而在叶子中,则是顺序查找的,所以,ASC排序会比DESC快一点。但如果是找4000这条记录,则DESC排序会快一点,因为第一条记录就是了。如果经常读取最后一条记录,则DESC会快一点。
聚集索引和非聚集索引的差别在于范围读取,因为聚集索引会将记录连续存储,所以可以连续读取。而非聚集索引不一定是连续存储,所以读取时,磁头可能会四处移动的。