假设表中有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.   

    设置1与设置2的排序存储应该就是你说的顺序你举的查找例子不太恰当,按你的逻辑,当查询20的时候desc是不是就占优势了呢既然你了解聚集索引是B树结构,或者说既然你有这样的疑问,应该先去了解一下索引查询的方式方法,当然这方面我了解的也不是很深,可以给你简单举个例子比如1-20个数据,每个数据页存储5个,那么占用了4个数据页,如果你要查询10这条数据,索引是要先定位10这条数据所在的数据页,比如2页,然后再进入数据页中进行检索
      

  2.   

    按照楼主说的,是在逐个页面比较了,事实上在B树的遍历时,不存在你说的跳过的情况,叶子节点是通过上层节点的入口地址进入的,从根节点开始,就已经知道下个节点要往哪里去了。
    这也是索引扫描 和 索引查找不一样的地方哦。不过对于索引树的遍历ASC/DESC确实有他的意义,尤其当遇到联合索引时。
      

  3.   


    先感谢两位,讨论讨论。我指的就是在B树最上面定位/遍历的过程
    如果是T级数据的时候,这个定位是从前往后还是从后往前,是否存在意义呢……
    同等条件下(索引、分区……等等所有条件),数据库越大速度也就越慢,也许也是因为这个原因咩?按照实际业务操作中,“查询”这个功能,在大多数情况下,都是从新往旧,也就是说最好是定义为DESC?
      

  4.   

    查找第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
      

  5.   

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

  6.   


    先谢谢Vidor和zbdzjx两位我去专家问答那问了一下邹建大神,回答很简单
    每级索引中的页均被链接在双向链接列表中,所以不存在需要严格区分ASC和DESC的情况
    也就是说无论ASC/DESC,数据库会优先使用效率较高的链接?
    (好像应该是这样理解)
    你的意思看懂了。
    主键应该就是设置为ASC,避免磁头往返移动。
    扩展一下,索引的ASC/DESC设置最好与主键一致,也就是ASC,也是避免磁头往返移动?
    是这么个说法?
    按照双向链接列表这个概念,其实应该不存在ASC/DESC这个问题,数据库自动找到最快的检索方案。--------结论一下--------
    按照:每级索引中的页均被链接在双向链接列表中,所以不存在需要严格区分ASC和DESC的情况
    1、不存在ASC/DESC的搜索速度问题,数据库会使用最佳搜索方案。
    过程可能包括根节点、页节点……等等
    2、ASC与DESC的设置,应该是用ASC,避免磁头的往返移动。理解不知道对不对。
      

  7.   

    也谢谢前面的szm341,seusoftware两位。
    容我暂不结贴,再次思考思考。
      

  8.   

    有一段时间没弄数据结构了,而且索引类型比较多,有些混乱了,所以大致说一下,不一定对。
    假如有10000条记录,1000条记录一个叶子,就是有10个叶子。
    在第一级,有一个节点,存放(1-10000),有两个指针,指向两个节点。
    第二级,两个节点(对应上一级),分别存放(1-5000)、(5001-10000),分别有五个指针,指向五个叶子。
    第三级,有两组,每组五个叶子,对应上一级的两个节点,存放(1-1000)、(1001-2000)……(9001-10000)
    所以,无论ASC/DESC,都可以很快的查找到相应的叶子。
    而在叶子中,是按顺序存放的,如ASC则存放1-1000;如DESC则存放1000-1。搜索时,也是按顺序一个一个找的。(这一级不会再往下分级了。)
    所以,1000条记录以内,索引就一级,就是按顺序从前往后找;1000~1000000条记录,是两级,就是一个节点加1000个叶子,由这个节点来确定在哪个叶子里,再在叶子里按顺序查找……
    因此,在从节点找到叶子的过程中,和ASC/DESC应该没多大关系。只是在叶子中的1000条记录时搜索时,才有关系。但实际过程中,从1000条记录里查找一条记录,应该是很快的。只有从索引中读取大量数据时,ASC/DESC才会有影响。
      

  9.   


    仔细看了两遍,按照里面说的1、最底层存储的量是大致固定的(比如1000条),数据库的性能在搜索1000条记录时,使用ASC/DESC,用户体验上是没有区别的。
    (如果再考虑双向链接列表的话,就更加没区别)
    (这个1000应该需要扩大,毕竟MSSQL的性能还是不错的,具体数字应该是属于非常快的处理范围内。)2、应该考虑的是数据越多,分支节点(或者说分支的层数)就越多
    这也是造成“数据越大搜索越慢”的原因。
    对于这个情况,我们使用分区的办法,降低每个区的数据量——也就是降低分支层数,这样来达到提高速度。这样理解?
      

  10.   

    基本上差不多,双向链表是必然的,所谓的物理顺序就靠链表来维持的,我画的就是双向箭头。5楼zbdzjx的理解或许有偏差1、索引叶级的Seek使用二分法查找,这个我测试过。其实到Seek到叶级的时候,数据页已经缓存了,无论二分法还是从头扫,速度都不会差很远,8k记录数最多1000出头。2、任何索引都是有序的,顺序扫描的磁头折返和碎片有关,2,1 <-> 4,3 <-> 6,5 <-> 8,7 <-> 10,9 这种情形的碎片是100%。只要下一页在前方,物理位置有间隔(当然不能太离谱)问题都不大,I/O最耗时是磁臂折返,折返100米和向前跑100米,不可同日而语。
      

  11.   


    谢谢,非常感谢。
    大致有个了解了,要进一步学习就真的需要实际测试分析了。对于主键的ASC/DESC关注点应该是在于:
    实际操作中磁头的往返移动及其所产生碎片对物理层的影响;而不是查找的效率问题。感谢!
    非常感谢各位的释义,觉得自己升华了~