MYSQL的Innodb和Myisam引擎的区别
- 事务,Innodb是支持事务的,而Myisam不支持。这是MYSQL将默认存储引擎从Myisam改成Innodb的重要原因之一。
- 锁的粒度,Innodb最小的锁粒度是行锁,Myisam最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新全部被阻塞,因此并发受限。这也是MYSQL将默认存储引擎从Myisam变成Innodb的重要原因之一。
- 读写:Innodb擅长更新频繁的操作,而Myisam擅长查询频繁操作。Innodb不保存表的行数,执行select count(*) from table 时需要扫描全表。而Myisam用一个变量保存了整张表的行数,执行上述语句只需要读出该变量即可,速度很快。
- 外键:Innodb支持外键,而Myisam不支持。对一个包含外键的Innodb表转为Myisam会失败。
- 聚簇索引:Innodb拥有聚簇索引,Myisam没有聚簇索引。关于聚簇索引详情见下。
关于Innodb和Myisam的聚簇索引问题
首先索引总共分为两大类:
- 聚簇索引(聚集索引)
- 辅助索引(非聚簇索引,二级索引)
- 聚簇索引的叶子节点是存储了完整的行数据,所以通过主键查找的行记录速度是最快的,只需要查一次索引树。
- 辅助索引的叶子节点并没有存储完整的行数据,需要先通过辅助索引的叶子节点得到主键值,然后在拿这个主键值去聚簇索引中查找对应的行记录,这里总共查找了两次,也被称为‘回表’,如何避免呢?可以使用索引覆盖,详情见下。
问题又来了,为什么Myisam既然没有聚簇索引查询速度也会比Innodb高呢 ?
Innodb在做select的时候,要维护的东西比Myisam引擎多得多。
- Innodb的聚簇索引的叶子节点存储的是数据文件(行记录),辅助索引存储了主键值。而Myisam是非聚簇索引,他的数据文件都是分离的,索引的叶子节点都是存储的数据文件的地址指针。假如都用的辅助索引,Innodb的辅助索引需要查找两遍树,而Myisam的索引只需要查询一遍树
- Innodb还需要维护MVCC一致;虽然可能你的场景没有,但是他还是需要去检查和维护,MVCC (Multi-Version Concurrency Control)多版本并发控制
聚簇索引一定是主键吗?
聚簇索引不一定是主键,但是主键一定是聚簇索引。
不建立主键的话是否就没有聚簇索引?
一个表可能没有主键,但是一定会有聚簇索引。因为如果没有定义主键,Innodb就会取第一个非空的唯一索引代替。如果没有这样的索引,Innodb会隐式创建一个内置的rowid作为聚簇索引。
如何避免‘回表’,什么是索引覆盖?
- 回表,其实就是上面说到的,先定位到主键值,在定位到行记录,它的性能较扫一遍的索引树更低,这就叫做'回表'
- 如何避免呢,可以使用索引覆盖。什么是索引覆盖?
索引覆盖就是select的数据只用从索引中就能够取到,不需要去读取一行数据。
- 示例1
主键是id,age是索引,name是普通字段
select *from table where age = 1;
这个就会回表,因为这里查询的是一整行的数据,而通过age索引只能查到age和主键id,所以Innodb又会通过主键id去聚簇索引上找一行的数据,这里就查了两次索引树。
优化:
select id,age from table where age = 1;
- 示例2
select id,age,name from table where age = 1;
这里也是会回表的,因为age索引树上找不到name,所以又会通过主键id去聚簇索引找到name值。
说说PHP的垃圾回收机制
php变量存在一个叫zval容器变量中。它的结构分为四部分:类型,值,is_ref和refcount。
- is_ref,是一个bool值,用来标志这个变量是否属于一个引用集合(其实就是如果用到了引用操作符),通过这个字节,php引擎才能把普通变量和引用变量区分开来。
- refcount,表示指向这个zval变量容器的变量的个数。
当refcount等于0,也就是没有变量指向这个变量容器zval时,该变量的内存空间将被释放。
session和cookie的区别与联系
区别
- 保存的位置:cookie保存在客户端,而session保存在服务端。
- 安全性:cookie不是很安全,别人可以分析放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
- 保存的数据大小:单个cookie保存的数据不能超过4K,很多浏览器都限制了一个站点最多保存20个cookie。而session是没有大小限制的
联系
session是依靠cookie的,sessionId就保存在cookie中,用户提交表单时,浏览器会默认的将cookie也带上,会将cookie里面的sessionId自动附在HTTP头信息中(这是浏览器自带的功能,用户不会察觉到),当浏览器处理完这个表单后,将结果返回给sessionId所对应的用户(试想,如果没有sessionId,当有两个用户同时注册的时候,服务器怎样才能知道到底哪个用户提交的哪个表单呢)。
那如果cookie被禁用了怎么办呢?
如果cookie被禁用,通常有两种方式实现session而不依赖cookie。
- URL重写,就是把sessionId直接附在URL路径的后面。
- 表单隐藏字段。比如:
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>