在之前的博文中简单提到了索引的分类与索引的可选择性查看:Click HERE

这片博客主要包含内容:索引组织表,索引算法B+树简单介绍

索引组织表

在innodb存储引擎中,表都是根据主键顺序组织存放的,使用这种存储方式的表就叫做索引组织表(index  organized table 简称IOT表)。

在innodb存储引擎中,每张表都有个主键(primary key),如果创建表是没有显式的定义主键,则INNODB存储引擎会按如下方式选择或创建主键。

  • 首先判断表中是否有非空唯一索引,如果有,则该列即主键。
  • 如果不符合上述条件,INNODB存储引擎会自动创建一个6字节大小的指针。

当表中有多个非空的唯一索引时,INNODB存储引擎将选择建表时第一个定义的非空唯一索引为主键。这里需要说明的是,主键的选择根据的是定义索引的顺序而不是建表时列的顺序

CREATE TABLE t1 (
    a INT NOT NULL,
    b INT NULL,
    c INT NOT NULL,
    d INT NOT NULL,
    UNIQUE KEY (b),
    UNIQUE KEY (d),
    UNIQUE KEY (c)
);

insert into t1 select 1,2,3,4;
insert into t1 select 5,6,7,8;
insert into t1 select 9,10,11,12;
#上面创建了表, 并且创建了索引,注意索引的顺序,然后插入了数据。
#使用字段_rowid可以查看表中的主键,_rowid只可以用来查看单列索引的主键。 #注意主键非空的唯一索引 mysql
> select a, b, c, d, _rowid from t1; +---+------+----+----+--------+ | a | b | c | d | _rowid | +---+------+----+----+--------+ | 1 | 2 | 3 | 4 | 4 | | 5 | 6 | 7 | 8 | 8 | | 9 | 10 | 11 | 12 | 12 | +---+------+----+----+--------+ 3 rows in set (0.00 sec) mysql>

这里提到INNODB存储引擎是索引组织表?那么在INNODB的内部是如何使用主键将表组织起来的呢?

INNODB存储引擎概述

存储引擎的索引分类(安装索引的内部实现不同):

  • B+树索引
  • 哈希索引(INNODB是自适应哈希索引)
  • 全文索引

B+树索引就是传统意义上的索引,也就是上面提到过那种类型的索引,这是目前关系型数据库系统中查找最为常用和最为有效的索引。B+树索引的构造类似于二叉树。

哈希索引,INNODB存储引擎是自适应的,INNODB存储引擎会根据表的使用情况自动为表生成哈希索引,不能认为干预是否在一张表中生成哈希索引。

全文索引,会在后面讲述。

B+树索引

B+树索引并不能找到一个给定键值的具体的行,只能找到这个记录所在的数据页。然后把这个数据页读到内存(innodb_buffer_pool_size)中,然后找到其中的记录。

一个问题:把对应的页读到内存中,那么是如何在这个页中找到对应的记录呢?

上面提到到INNODB时索引组织表,是按照主键的顺序排放的,这里按照顺序是按照逻辑顺序存放的,每个页之间通过双向链表链接。但是数据在一个物理页上却是物理有序的。也就是说,读到内存中的这个页是物理有序,这时候我们要在这个有序的队列中找到想要的记录,就会很方便了。但是这里具体是怎么查找的?INNODB使用的是二分查找法。

二分查找法

二分查找法也称折半查找法,用来查找一组有序的记录数组中某一记录,其基本思想是:将记录按有序化排列,在查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该元素中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半。

通过一个例子说明二分查找法:
一个有序数列如下:
5  10  19  21  23   25    27  31   33
寻找31这个数字:
第一次找到中间数23,
31>23, 所以第二次要在后半段查找也就是23 25 27  31  33中查找。
然后重复上面的步骤。

注意:二分查找法通过降低比较的次数,也就是降低的是cpu的使用。
#!/usr/bin/env python
#*-* coding:utf -8 *-*
#二分法查找数值

import sys
import random

def UnsortList():         ###如果没有指定参数,随机生成一个序列
    list = []
    long = random.randint(0,100)
    for i in range(long):
        list.append(random.randint(0,10000))
    return list

def BinarySearch(list, mark, low=0,uplow=None):   #二分法查找
    if not uplow:
        uplow = len(list) -1
    if low == uplow:
        assert mark == list[uplow]
        return uplow
    else:
        mid = (low + uplow) // 2
        if mark > list[mid]:
            return BinarySearch(list, mark,mid+1,uplow)
        else:
            return  BinarySearch(list,mark,low,uplow=mid)    

def SuijiMark(list):            ###在列表中随机挑选一个要查找的数据
    l = len(list)
    mark = list[random.randint(0,l) - 1]
    return mark

def main():           ####主函数
    Ulist = []
    print "1:随机产生列表,验证二分法"
    print "2:用户自己输入数值生成列表,验证二分法"
    answer = input("请输入对应的数字: ")
    if answer == 1:
        Ulist = UnsortList()
        mark = SuijiMark(Ulist)
        print "The list is %s" % Ulist
        print "The mark is %s" % mark
        print "The len of the list is %s " % len(Ulist)
    elif answer == 2:
        lang = input("请输入列表长度: ")      ##根据输入的数值,组成列表
        for i in range(lang):          
            Ulist.append(input("请输入列表第%d个值:" % (i + 1)))
        mark = SuijiMark(Ulist)
        print "the list is %s" % Ulist
        print "the mark is %s" % mark
    else:
        print "请输入合法的数字"
    Ulist.sort()
    index = BinarySearch(Ulist, mark)
    print "The index %s is %s" % (index, mark)


if __name__ == "__main__":
    main()
用python写的二分查找法,python2.6版本

相关文章:

  • 2022-02-27
  • 2022-03-02
  • 2021-08-15
  • 2022-12-23
  • 2022-12-23
  • 2018-02-14
  • 2021-12-10
猜你喜欢
  • 2022-02-14
  • 2021-11-06
  • 2021-10-04
  • 2021-10-16
  • 2021-10-25
相关资源
相似解决方案