第一次面试总结——索引、排序

目录

1.索引

*1.索引是加速检索表中数据的机制、结构

*2.适合添加索引的情况

*3.不适合添加索引的情况

4.索引失效的情况

5.B树与B+树的选择

6.为什么建议InnoDB表必须建主键

7.为什么推荐使用自增主键

8. 为什么InnoDB非主键索引存储的是主键值

*2.排序算法

1.冒泡排序

2.快速排序

3.简单选择排序——每次选择最小的(不稳定,552)

4.直接插入排序——把新元素插入已经有序的队列

5.归并排序


1.索引

*1.索引是加速检索表中数据的机制、结构

在数据之外,数据库还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用指向数据,这样就可以在这些数据结构上实现高效查找,这些数据结构就是索引。

*2.适合添加索引的情况

  1. 主键自动建立唯一索引。
  2. 频繁作为where条件语句查询的字段
  3. 关联字段需要建立索引,例如外键字段,student表中的classid, classes表中的schoolid 等
  4. 排序字段可以建立索引
  5. 分组字段可以建立索引,因为分组的前提是排序
  6. 统计字段可以建立索引,例如count(),max()

*3.不适合添加索引的情况

       1)表数据太少,唯一性较差的字段

       2)频繁增删改的字段

       3)where后面用不到的字段

4.索引失效的情况

  1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
  2.对于多列索引,不是使用的第一部分,则不会使用索引
  3.like查询是以%开头
  4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

  5.当查询条件存在隐式转换时,索引会失效。查询未加字符串单引号时

  6.where语句中使用了IS NULL或者IS NOT NULL,会造成索引失效

  7.在where列中使用了函数,列进行了运算

  8.如果mysql估计使用全表扫描要比使用索引快,则不使用索引????

5.B树与B+树的选择

B+Tree特点:

  1)非叶子节点不存储数据,只存索引(冗余),这样可以保证存放更多的索引 

  2)叶子节点存储所有索引字段

  3)叶子节点用指针连接,提高区间访问性能

B+树的查询效率更加稳定,因为数据放在叶子节点
B+树能提高范围查询的效率,因为叶子节点指向下一个叶子节点

1.、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

6.为什么建议InnoDB表必须建主键

首先,我们知道InnoDB采用B+树作为存储结构,那么必然需要一个列作为key,什么是key?

如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

降低数据库的开销?

 

7.为什么推荐使用自增主键

据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)

如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页

如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

 

8. 为什么InnoDB非主键索引存储的是主键值

减少了出现行移动或者数据页分裂时二级索引的维护工作(当数据需要更新的时候,二级索引不需要修改,只需要修改聚簇索引,一个表只能有一个聚簇索引,其他的都是二级索引,这样只需要修改聚簇索引就可以了,不需要重新构建二级索引)

MySQL索引面试题汇总_持之以恒,方得始终-CSDN博客_mysql索引面试题

 

*2.排序算法

十大排序算法的实现以及各自的优缺点、适用情况_derbi123123的博客-CSDN博客_排序算法优缺点

1.冒泡排序

    public void BubbleSort(int[] arr){
        if(arr==null)   return;
        for(int i=0;i<arr.length;i++){
            for(int j=i+1;j<arr.length;j++){
                if(arr[i]>arr[j]) {
                    swap(arr, i, j);
                }
            }
        }
    }
    public void BubbleSort(int[] arr){
        if(arr==null)   return;
        for(int i=0;i<arr.length;i++){
            boolean flag=false;
            for(int j=i+1;j<arr.length;j++){
                if(arr[i]>arr[j]) {
                    flag=true;
                    swap(arr, i, j);
                }
            }
            if(!flag) return;
            System.out.println(i);
        }
    }

适用情况:待排序的元素规模小,(PS稳定)

已经有序的情况——O(N)

2.快速排序

    public void quickSort(int[] arr,int l,int r){
        if(l<r){
            int a=l+(int)(Math.random()*(r-l+1));
            System.out.println(a);
            swap(arr,a,l);
            int mid=patition(arr,l,r);
            quickSort(arr,l,mid-1);
            quickSort(arr,mid+1,r);
        }
    }

    public int patition(int[] arr,int l,int r){
        int i=l,j=r;
        int key=arr[l];
        while(i<j){
            while(arr[j]>=key && i<j)  j--;
            if(i<j) arr[i++]=arr[j];
            while(arr[i]<key && i<j)    i++;
            if(i<j) arr[j--]=arr[i];
        }
        arr[i]=key;
        return i;
    }

荷兰国旗问题

    public void hollandFlag(int[] arr,int l,int r,int value){
        int less=l-1;
        int more=r+1;
        int cur=l;
        while(cur<r){
            if(arr[cur]<value)
                swap(arr,cur++,++less);
            else if(arr[cur]>value)
                swap(arr,--more,cur);
            else cur++;
        }
        System.out.println(Arrays.toString(arr));
    }

快速排序是冒泡排序的改良版

优点:较快(无序的情况下),数据移动少;

缺点:不稳定。有序的情况下比较次数会变多(正序、倒序、相等)

适用:数据分布比较平均

3.简单选择排序——每次选择最小的(不稳定,552)

void SimpleChooseSort(int A[],int N)//序列A及元素个数
{
	for(int i=0;i<N;i++){
		int min=i;
		for(int j=i+1;j<N;j++){//寻找i后面的最小元素下标 
			if(A[min]>A[j])
				min=j;
		}
		if(min==i) continue;//如果i后面的元素都大于等于i,那么 min还是i,就不用了交换了 
		swap(A[i],A[min]); //交换 
	}	
} 

4.直接插入排序——把新元素插入已经有序的队列

 public void simpleInsertSort(int[] arr){
        for (int i = 1; i < arr.length; i++) {
            int tmp=arr[i];
            int j;
            for(j=i;j>0&&arr[j-1]>tmp;j--)
                arr[j]=arr[j-1];
            arr[j]=tmp;
        }
    }

5.归并排序

    public void sort(int[] arr){
        if(arr==null||arr.length<2) return;
        sort1(arr,0,arr.length-1);

    }
    public void sort1(int[] arr,int l,int r){
        if(l<r){
            int m=l+((r-l)>>1);
            sort1(arr,l,m);
            sort1(arr,m+1,r);
            merge(arr,l,m,r);
        }
    }
    public void merge(int[] arr,int l,int m,int r){
        int[] tmp=new int[r-l+1];
        int i=0;
        int p1=l,p2=m+1;

        while(p1<=m&&p2<=r){
            tmp[i++]=arr[p1]<=arr[p2]?arr[p1++]:arr[p2++];
        }
        while(p1<=m)
            tmp[i++]=arr[p1++];
        while(p2<=r)
            tmp[i++]=arr[p2++];
        i=0;
        while(l<=r)
            arr[l++]=tmp[i++];
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值