目录
1.索引
*1.索引是加速检索表中数据的机制、结构
在数据之外,数据库还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用指向数据,这样就可以在这些数据结构上实现高效查找,这些数据结构就是索引。
*2.适合添加索引的情况
- 主键自动建立唯一索引。
- 频繁作为where条件语句查询的字段
- 关联字段需要建立索引,例如外键字段,student表中的classid, classes表中的schoolid 等
- 排序字段可以建立索引
- 分组字段可以建立索引,因为分组的前提是排序
- 统计字段可以建立索引,例如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索引面试题汇总_持之以恒,方得始终-优快云博客_mysql索引面试题
*2.排序算法
十大排序算法的实现以及各自的优缺点、适用情况_derbi123123的博客-优快云博客_排序算法优缺点
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++];
}