1、mysql 数据库中 delete 对背后数据内存有没有影响,会不会产生垃圾空间,空间是否会回收
(涉及到数据库背后引擎实现,文件机制,b+树)
1、drop table table_name 立刻释放磁盘空间 ,不管是 InnoDB和MyISAM
2、truncate table table_name 立刻释放磁盘空间 ,不管是 Innodb和MyISAM 。
truncate table其实有点类似于drop table 然后create。只不过这个create table 的过程做了优化,比如表结构文件之前已经有了等等,就不需要重新再搞一把。所以速度上应该是接近drop table的速度。
3、对于delete from table_name 删除表的全部数据
对于MyISAM 会立刻释放磁盘空间 (应该是做了特别处理,也比较合理); InnoDB 不会释放磁盘空间
4、对于delete from table_name where xxx带条件的删除
不管是innodb还是MyISAM都不会释放磁盘空间。
5、delete操作以后 使用optimize table table_name 会立刻释放磁盘空间。不管是InnoDB还是MyISAM 。
所以要想达到清理数据的目的,请delete以后执行optimize table 操作。
6、delete from表 以后虽然未释放磁盘空间,但是下次插入数据的时候,仍然可以使用这部分空间
2、回收 mysql 空间几种方法以及问题
1、OPTIMIZE TABLE
OPTIMIZE TABLE 会重组表和索引的物理存储,减少对存储空间使用和提升访问表时的IO效率。对每个表所做的确切更改取决于该表使用的存储引擎
OPTIMIZE TABLE的支持表类型:INNODB,MYISAM, ARCHIVE,NDB;它会重组表数据和索引的物理页,对于减少所占空间和在访问表时优化IO有效果。
OPTIMIZE 操作会暂时锁住表,而且数据量越大,耗费的时间也越长。
OPTIMIZE TABLE后,表的变化跟存储引擎有关。
对于MyISAM, PTIMIZE TABLE 的工作原理如下:
如果表有已删除的行或拆分行(split rows),修复该表。
如果未对索引页面进行排序,对它们进行排序。
如果表的统计信息不是最新的(并且无法通过对索引进行排序来完成修复),更新它们。
2、ALTER TABLE table_name ENGINE = Innodb;
这其实是一个NULL操作,表面上看什么也不做,实际上重新整理碎片了.当执行优化操作时,实际执行的是一个空的 ALTER 命令,
但是这个命令也会起到优化的作用,它会重建整个表,删掉未使用的空白空间.
问题1:那么是用OPTIMIZE TABLE 还是ALTER TABLE xxxx ENGINE= INNODB好呢?
其实对于InnoDB引擎,ALTER TABLE xxxx ENGINE= INNODB是执行了一个空的ALTER TABLE操作。而OPTIMIZE TABLE等价于ALTER TABLE ... FORCE。 参考上面描述,在有些情况下,OPTIMIZE TABLE 还是ALTER TABLE xxxx ENGINE= INNODB基本上是一样的。但是在有些情况下,ALTER TABLE xxxx ENGINE= INNODB更好。例如old_alter_table系统变量没有启用等等。另外对于MyISAM类型表,使用ALTER TABLE xxxx ENGINE= INNODB是明显要优于OPTIMIZE TABLE这种方法的。
问题2:ALTER TABLE xxxx ENGINE= INNODB 表上的索引碎片会整理么
ALTER TABLE ENGINE= INNODB,会重新整理在聚簇索引上的数据和索引。如果你想用实验验证,可以对比执行该命令前后index_length的大小。
2、有没有碰到 mysql 索引失效的情况,怎么解决 ?
1.索引无法存储null值
a.单列索引无法储null值,复合索引无法储全为null的值。
b.查询时,采用is null条件时,不能利用到索引,只能全表扫描。
为什么索引列无法存储Null值?
a.索引是有序的。NULL值进入索引时,无法确定其应该放在哪里。(将索引列值进行建树,其中必然涉及到诸多的比较操作,null 值是不确定值无法
比较,无法确定null出现在索引树的叶子节点位置。)
b.如果需要把空值存入索引,方法有二:其一,把NULL值转为一个特定的值,在WHERE中检索时,用该特定值查找。其二,建立一个复合索引。例如
create index ind_a on table(col1,1); 通过在复合索引中指定一个非空常量值,而使构成索引的列的组合中,不可能出现全空值。
2.不适合键值较少的列(重复数据较多的列)
假如索引列TYPE有5个键值,如果有1万条数据,那么 WHERE TYPE = 1将访问表中的2000个数据块。
再加上访问索引块,一共要访问大于200个的数据块。
如果全表扫描,假设10条数据一个数据块,那么只需访问1000个数据块,既然全表扫描访问的数据块
少一些,肯定就不会利用索引了。
3.前导模糊查询不能利用索引(like '%XX'或者like '%XX%')
假如有这样一列code的值为'AAA','AAB','BAA','BAB' ,如果where code like '%AB'条件,由于前面是
模糊的,所以不能利用索引的顺序,必须一个个去找,看是否满足条件。这样会导致全索引扫描或者全表扫
描。如果是这样的条件where code like 'A % ',就可以查找CODE中A开头的CODE的位置,当碰到B开头的
数据时,就可以停止查找了,因为后面的数据一定不满足要求。这样就可以利用索引了。
4.索引失效的几种情况
1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2.对于多列索引,不是使用的第一部分,则不会使用索引
3.like查询以%开头
4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引
5.MySQL主要提供2种方式的索引:B-Tree索引,Hash索引
B树索引具有范围查找和前缀查找的能力,对于有N节点的B树,检索一条记录的复杂度为O(LogN)。相当于二分查找。
哈希索引只能做等于查找,但是无论多大的Hash表,查找复杂度都是O(1)。
显然,如果值的差异性大,并且以等值查找(=、 <、>、in)为主,Hash索引是更高效的选择,它有O(1)的查找复杂度。
如果值的差异性相对较差,并且以范围查找为主,B树是更好的选择,它支持范围查找。
3、quatrz 碰到海量数据怎么解决?
1、一个job,多个机器运行,用哈希算法负载均衡
2、物理多线程解决
3、Spring整合Quartz分布式调度
https://segmentfault.com/a/1190000014539816
4、mysql 分区类型
RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。
LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。
HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。
KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
算法题:
1、取 第 k 个最大的数据,复杂度是多少?时间越快越好
假设数组为array,求第K大的元素。
注意:因为快排排序后,数组是由小到大的,所以第K大的元素为倒数第十个即 array[array.length-K+1];
所以我们要令k =array.length-K+1
思路:利用快排的分治思想,先对数组进行一趟快排,将数组分为三个区,(0,par),(par),(par+1,array.length-1)。判断k与par的大小,如果par +1<k,那么下次对(par+1,array.length-1)这一部分进行快排,如果par+1>k,则对(0,par-1)进行快排。直到par == k,那么第K大的数就是array[par].
为什么说时间复杂度为O(N),第一次分区查找,我们需要对n个元素进行分区,第二次分区查找,需要对n/2个元素进行分区。依次类推,直到区间缩小为1.那么总时间复杂度为:n+n/2+n/4+n/8+...+1,等比数列求和,和为2n-1。所以时间复杂度为O(N).
代码如下:
import java.util.Random;
public class FindK {
public static void main(String[] args) {
Random r = new Random();
int K = 10;//第K大的数
int[] array = new int[4000];
for(int i =0 ;i<array.length;i++){
array[i] = r.nextInt(4000);
}
//快排排出来是由小到大的,所以第K大的数,也就是倒数第十个数,
//即k=array.length-K+1
int k = array.length-K+1;
int par = parton(array,0,array.length-1);
while(par + 1 != k){
if(par+1<k){
par = parton(array,par+1,array.length-1);
}else if(par+1>k) {
par = parton(array,0,par-1);
}
}
System.out.println(array[par]);
}
public static int parton(int[] array,int l,int h){
if(l<h){
int tmp = array[l];
while(l<h){
while(l<h && array[h]>=tmp){
h--;
}
if(l<h){
array[l++] = array[h];
}
while(l<h && array[l]<=tmp){
l++;
}
if(l<h){
array[h--] = array[l];
}
}
array[l] = tmp;
return l;
}
return -1;
}
}
2、字符串转为整数,考虑异常情况
public static Integer trafer(String str) {
str = str.replace(" ", "");
System.out.println("str: " + str);
String res = "1";
char[] strArray = str.toCharArray();
if (str.charAt(0) == '-' || Character.isDigit(strArray[0])) {
Pattern pattern = compile("([0-9]|-)[0-9]{1,}");
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
res = matcher.group(0);
}
} else {
return 0;
}
Integer result = Integer.valueOf(res);
if (Integer.valueOf(result) < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
if (Integer.valueOf(result) > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
return result;
}
3、输入字符串 abc 输出他们多个组合,比如 abc acb bca bac cab cba
public class TenXunTest3 {
public static void main(String[] args){
String str = "abc";
List<String> result = new ArrayList<String>();
getAllLists(result,str,"");
for(String each : result){
System.out.println(each);
}
}
/**
* @param base 以该字符串作为基础字符串,进行选择性组合。
* @param buff 所求字符串的临时结果
* @param result 存放所求结果
*/
public static void getAllLists(List<String> result, String base, String buff){
if(base.length() <= 0){
result.add(buff);
}
for(int i = 0; i < base.length(); i++){
getAllLists(result, new StringBuilder(base).deleteCharAt(i).toString(),
buff + base.charAt(i));
}
}
}