计算得出非连续数字分段

<?php

$array = array(10010,10011,10012,10013,10015,10016,10026,10027,10028,10029);

$range = get_num_range($array);

print_r($range);

function get_num_range($arr){

    $range = array();

    $i = 1;

    $tmp_min = $tmp_max = '';

    foreach($arr as $no){

        //如果没有此range的最小值 第一个就是最小值

        if(empty($tmp_min)){

            $tmp_min = $no;

        }

        //下一个值不存在计算出最大值

        $next_no = $no+1;

        if(!in_array($next_no,$arr) && !empty($next_no)){

            $tmp_max = $no;

            $range[] = array($tmp_min, $tmp_max);

            $tmp_min = '';

        }

    }

    return $range;

}

?>

MySQL 事务,锁

ACID

  • Atomic同一个事务里,要么都提交,要么都回滚

  • Consistency即在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏

  • Isolation 并发事务间的数据是彼此隔离的

  • Durabiliy 事务提交后,所有结果务必被持久化

支持事务:InnoDB,NDBCluster, TokuDB

不支持事务:MyISAM,MEMORY

  1. 隔离性通过锁实现

  2. 原子性,一致性,持久性通过数据库的redo和undo来完成

撤销日志: UNDO LOG (现在正在活跃的事务,但还没有提交,或者还没有完成check point)

重做日志:REDO LOG (已经提交的事务)

REDO 和 UNDO 在做数据库恢复的时候的作用是相反的,

RODO:在做数据库恢复的时候,如果有事务还没有真正的提交,那么需要前滚(扫描RODO LOG检查哪些事务已经提交了,但还没有持久化到数据文件【table spacs, data table spage】里的,再把这些重做一次事务【再重新提交一次】)

UNDO: 正好是相反 找到还没有提交的事务 但是再undo log里需要进行一次回滚,就是把已经提交的事务回滚掉

在做数据库恢复的时候要做这样的一个过程

autocommit = 0|1

设置事务自动 开启|关闭

显示事务 启动 | 关闭

  1. 以START TRANSACTION/BEGIN开始事务

  2. 以COMMIT/ROLLBACK TRANSACTION结束事务

隐性事务提交

主要是DDL,DCL会引发事务的隐性提交

SQL四种语言:DDL,DML,DCL,TCL

MySQL 多列索引的生效规则

mysql中 myisam,innodb默认使用的是 Btree索引,至于btree的数据结构是怎样的都不重要,
只需要知道结果,既然是索引那这个数据结构最后是排好序;就像新华字典他的目录就是按照a,b,c..这样排好序的;
所以你在找东西的时候才快,比如你找 “中” 这个字的解释,你肯定就会定位到目录的 z 开头部分;

组合索引可以这样理解,比如(a,b,c),abc都是排好序的,在任意一段a的下面b都是排好序的,任何一段b下面c都是排好序的;

713671-20170223142607007-29450957.png

组合索引的生效原则是  从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用;
比如

where a=3 and b=45 and c=5 .... 这种三个索引顺序使用中间没有断点,全部发挥作用;
where a=3 and c=5... 这种情况下b就是断点,a发挥了效果,c没有效果
where b=3 and c=4... 这种情况下a就是断点,在a后面的索引都没有发挥作用,这种写法联合索引没有发挥任何效果;
where b=45 and a=3 and c=5 .... 这个跟第一个一样,全部发挥作用,abc只要用上了就行,跟写的顺序无关

(a,b,c) 三个列上加了联合索引(是联合索引 不是在每个列上单独加索引)

还需注意,  (a,b,c)多列索引和 (a,c,b)是不一样的,看上面的图也看得出来关系顺序是不一样的;
分析几个实际例子来加强理解;
分析句子中使用的索引情况

select * from mytable where a=3 and b=5 and c=4;
abc三个索引都在where条件里面用到了,而且都发挥了作用

select * from mytable where  c=4 and b=6 and a=3;
这条语句列出来只想说明 mysql没有那么笨,where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样

select * from mytable where a=3 and c=7;
a用到索引,b没有用,所以c是没有用到索引效果的

select * from mytable where a=3 and b>7 and c=3;
a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引

select * from mytable where b=3 and c=4;
因为a索引没有使用,所以这里 bc都没有用上索引效果

select * from mytable where a>4 and b=7 and c=9;
a用到了  b没有使用,c没有使用

select * from mytable where a=3 order by b;
a用到了索引,b在结果排序中也用到了索引的效果,前面说了,a下面任意一段的b是排好序的

select * from mytable where a=3 order by c;
a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort

select * from mytable where b=3 order by a;
b没有用到索引,排序中a也没有发挥索引效果

MySQL 索引使用笔记

用voucher表来做单表测试

  1. 创建voucher_id为主键

  2. 创建voucher_idx(voucher_id, prefix, voucher_no)

    image.png

当我查主键的时候毫无疑问 肯定是走主键索引的

image.png

当我只查找主键字段的时候 Extra显示“Using index”不回表直接使用到覆盖索引

image.png

可以看到 当查询条件里有主键的时候 查询会直接用主键查询 可能是因为主键是唯一索引 直接就定位到是最简方法

image.png

下面不用主键来做条件, 直接用voucher_idx里的字段来查找

可以看到type变成了ref 不再是有主键时的const

ref:是一种索引访问(有时也叫索引查找),它返回所有匹配某个单个值的行。然而,它可能会找到多个符合条件的行,因此它是查找和扫描的混合体…

可以看到找到了45310条记录,测试的voucher总数是319814  45310/319814≈0.15 不到30%所以还是能使用索引的

image.png

但是这就不对了 prefix是‘A10’的占了76% 还是能用到索引 是不是说明“一个值超过30%就无法使用索引”的描述? 可能是新版功能加强了吧

image.png

这个确实能证实,不是从索引左侧的列搜索用不到索引,这条语句扫描了319814行

image.png

下面这个语句 其实说明了不按索引顺序 也是能用到索引的 应该是索引优化器把where里的索引列又排了下

image.png

查了一下优化器执行的代码 好像也没有对索引重排 看来还是service层做了优化让我们能使用到索引?

image.png

我又创建了一个索引voucher_idx2,我以为搜索条件是voucher_no, prefix和 prefix,voucher_no的时候会不一样,结果都用到了voucher_idx2

image.png

image.png

image.png

这可以说明当查询条件和搜索条件都在索引内时,不按索引顺序也是能用到索引的,但是扫描了全表

image.png

image.png

但是查询列或者搜索列里有不在索引列里的列的时候 是会扫描全表的

image.png

image.png

那我把所有列都拿进来 是不是都能用到索引?? 

image.png 

可以看到,其实是走了索引,但是也是扫了全表,效率应该相当差, 需要用数据量很大的库来试一下,如果不按索引顺序来跑的效率

image.png

MySQL 什么情况下无法使用索引

  1. 通过索引扫描的记录超过30%,变成全表扫描

  2. 联合索引中,第一个索引列使用范围查询

  3. 联合索引中,第一个查询条件不是最左索引列

  4. 模糊查询条件列最左以通配符%开始

  5. 内存表(HEAP)表使用HASH索引时,使用范围检索或者ORDER BY

  6. 两个独立索引,其中一个用于检索,一个用于排序

  7. 使用了不同的ORDER BY 和 GROUP BY 表达式

  8. 索引列检索使用函数 

  9. 两表连接的时候如果连接字段类型不一致是无法使用索引的(其实可以使用,但是需要进行隐式转换,导致没有办法2个表都使用到索引,只有一个表能用到索引,另一个表被隐式转换了 用不到索引 )

2个独立的索引 and的情况下只能用到一个索引,or的情况下可以用到index mearge把结果联合起来

image.png

image.png

image.png

image.png

image.png

image.png

MySQL key_len计算规则

  1. 索引字段的附加信息:可以分为变长和定长数据类型讨论,当索引字段为定长数据类型,比如char,int,datetime,需要有是否为空的标记,这个标记需要占用1字节;对于变长数据类型,比如:varchar,除了是否为空的标记外,还需要有长度信息,需要占用2个字节;

    (备注:当字段定义为非空的时候,是否为空的标记将不占用字节)

  2. 同时还需要考虑表所使用的字符集,不同的字符集,gbk编码的为一个字符2个字节,utf8的一个字符3个字节

总结, key_len的长度计算公式:

image.png

key_len是表示得到结果集所使用的选择的索引的长度,但不包括order by,也就是说,如果order by也使用了索引则ket_len则不计算在内

MySQL Explain

usering index — 覆盖索引

usering filesort — 使用filesort排序算法,对查询结果进行排序(该排序工作无法通过索引的排序直接完成,简而言之,就是要排序的列无索引)

5.6版本以上,才支持EXPLAIN DELETE/UPDATE

MYSQL explain详解

http://blog.csdn.net/zhuxineli/article/details/14455029