1.插入缓冲
2.两次写
3.自适应哈希索引
4.异步io
5.刷新临近页
mysql 文件介绍
日志文件
1.error.log 错误日志:
mysql> show variables like "log_error";
+---------------+---------------------------------------------+
| Variable_name | Value |
+---------------+---------------------------------------------+
| log_error | /Users/itech8/data/apps/logs/mysql/error.log |
+---------------+---------------------------------------------+
1 row in set (0.01 sec)
2.慢查询日志, 默认慢查询日志时间设置的是10秒
mysql> show variables like "long_query_time";
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.01 sec)
慢查询日志文件位置:
mysql> show variables like "slow_query_log%";
+---------------------+------------------------------------------------------------------+
| Variable_name | Value |
+---------------------+------------------------------------------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /Users/itech8/data/apps/appdata/mysql/itech8deMacBook-Air-slow.log |
+---------------------+------------------------------------------------------------------+
2 rows in set (0.00 sec)
慢查询日志分析
mysqldumpslow Users/itech8/data/apps/appdata/mysql/itech8eMacBook-Air-slow.log
获取执行时间最长的10条记录
mysqldumpslow -s -al -n 10 Users/itech8data/apps/appdata/mysql/itech8eMacBook-Air-slow.log
也可以将慢查询日志放到table中,默认文件中
SET Global log_output='TABLE'
3.全局查询日志
mysql> show variables like "general_log%";
+------------------+-------------------------------------------------------------+
| Variable_name | Value |
+------------------+-------------------------------------------------------------+
| general_log | OFF |
| general_log_file | /Users/itech8/data/apps/appdata/mysql/itech8deMacBook-Air.log |
+------------------+-------------------------------------------------------------+
2 rows in set (0.00 sec)
开启全局日志
mysql> set global general_log=on;
Query OK, 0 rows affected (0.00 sec)
4.二进制日志
/etc/my.conf下添加
log-bin=mysql-bin-log
binlog_format=mixed
max_bin_size:记录单个二进制文件的最大值:mysql-bin-log.00001 内容超过max_bin_size设置的最大值,产生一个新的二进制文件,后缀+1
binlog_cache_size:事务未提交,所有未提交的二进制日志会被记录到一个缓存中,等该事务提交时直接将缓冲的二进制日志写入二进制文件中
用处:复制-故障恢复-sql审计
sync_binlog=[n]表示每写缓冲多少次就同步到磁盘,sync_binlog=1表示同步磁盘的方式来实时写二进制文件,不用操作系统的缓冲,默认值是0
innodb_support_xa
binlog_format
streamant、raw、mixed
pid文件
mysql启动实例的时候会将自己的进程id写入文件
mysql> show variables like "pid_file";
+---------------+-------------------------------------------------------------------+
| Variable_name | Value |
+---------------+-------------------------------------------------------------------+
| pid_file | /Users/itech8/data/apps/appdata/mysql/itech8deMacBook-Air.local.pid |
+---------------+-------------------------------------------------------------------+
1 row in set (0.00 sec)
套接字socket文件位置
mysql> show variables like "socket";
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| socket | /tmp/mysql.sock |
+---------------+-----------------+
1 row in set (0.00 sec)
表结构和innodb存储引擎文件
.frm
innodb的表空间文件
默认配置下会有一个初始大小10mb的ibdata1文件,可以用多个文件组成一个表空间,例如:ibdata1和ibdata2组成一个表空间,假设两个文件在不同磁盘上,磁盘负载被平均
因此可以提高数据库整体性能
若innodb_data_file_path:所有的表数据都会记录到该共享表空间中
若innodb_file_per_table:每个表都会产生一个独立的表空间,表名:.ibd,单个表默认大小是96kb,这些单独的表空间,仅存储该表的数据,索引,和插入缓冲Bitmap信息,其余信息还是放在默认共享表空间中
innodb的重做日志文件
默认情况下,innodb存储引擎数据目录下都会有这两个文件ib_logfile0和ib_logfile1,这是innodb引擎的重做日志文件(redo log file)
每次存储引擎下至少有1个重做日志文件组,每个组下卖弄至少有2个重做日志文件,如默认的ib_logfile0和ib_logfile1,可以将不同的文件组放在不同的磁盘上,提高重做日志的高可用性,
redo log file和回滚日志文件 undo log file
表
1.索引组织表
如果创建表时候没有显示定义表主键,那么innodb会根据以下方式选择或者创建主键
a.首先判断表中是否有非空的唯一索引(union not null) 如果有,则该列为主键,当表中有多个非空唯一索引时候,innodb会选择建表时候第一个定义的非空唯一索引为主键,注意,主键的选择根据的是定义索引的顺序,而不是建表时候列的顺序
CREATE TABLE `z` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
UNIQUE KEY `b` (`b`),
UNIQUE KEY `d` (`d`),
UNIQUE KEY `c` (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `z` (`a`, `b`, `c`, `d`)
VALUES
(1, 1, 1, 1),
(2, 2, 2, 2);
可以看到主键是d 列
mysql> select _rowid,a,b,c,d from z;
+--------+---+------+---+---+
| _rowid | a | b | c | d |
+--------+---+------+---+---+
| 2 | 2 | 3 | 2 | 2 |
| 4 | 1 | 2 | 3 | 4 |
+--------+---+------+---+---+
2 rows in set (0.00 sec)
b.如果不符合上述条件,innodb会自动创建一个6字节大小的指针
innodb 逻辑存储结构
tablespce表空间又段,区,页组成
段:索引段-B+tree的非叶子节点, 数据段:B+tree的叶子节点,回滚段
区:连续页组成的空间,任何情况下,每个区的大小都为1MB,为保证去的连续性,innodb一次从磁盘申请4-5个区,默认innodb存储的引擎页大小是16kb,即一个区一共16个连续的页
页:是innodb磁盘管理最小的单位,默认每个页的大小是16kb,也可以通过参数innodb_page_size设置每页的大小是4k,8k,16k
常见的数据页类型:数据页,undo页,系统页,事务数据页等等
行:
innodb 是按行存放数据的,每页存放的行记录最多允许存放 16kb/2-200行记录,即7992行
索引和算法
B+tree 索引不能找到一个给定键值的具体行,B+tree树索引能找到的知识被查找数据行所在的页,然后数据库通过把页读入内存中,再在内存中查找,得到要查找的数据
1,2,3,4,5,6,7,8,9,10
1.tinyint和Enum
2.索引和算法
二叉查找树->平衡二叉树->Btree->B+tree
二叉查找树:左子树的键值总是小于根的键值,右子树的键值总是大于根的键值
2-3-6-7-8
6
/ \
3 7
/ \ \
2 5 8
插入新值9,为了保持平衡,需要旋转一次,有时候需要旋转多次,因此维护一颗平衡二叉树需要开销的
6
/ \
3 7
/ \ / \
2 5 8 9
查找8 先找到根节点6 ,6小于8,因此查找右子树,需要查找3次,顺序查找的话则需要6次
定义:平衡二叉树(AVL)查找效率高,满足二叉树的定义外,而且任意节点的两个子树高度最大差为1
B+tree
所有数据存放在叶子节点上,并且是顺序存放的,如果用户从左边的叶子节点是顺序遍历,可以得到所有键值的顺序排序,叶子节点之间是个双向链表指针
B+tree 索引分为聚簇索引和辅助索引,其内部都是B+tree,高度平衡的,叶子节点存放数据,B+tree索引,内部其实是B+tree在mysql中的实现
B+tree在数据库中是高扇出性,一般在DB中B+树的高度在2-3层左右。也就意味着只需要2-3次的IO操作即可。而现在的磁盘每秒差不多在100次IO左右,2-3次意味着查询时间只需0.02-0.03秒。
聚集索引,
InnoDB存储引擎表是索引组织表,即表中数据安装主键顺序存放。而聚集索引就是按照每张表的主键构造一颗B+,并且叶节点存放着整张表的行记录数据,因此也将聚集索引的叶子节点称为数据页。
聚簇索引的这个特性也决定了索引组织表中的数据也是索引的一部分,同B
实际的数据页只能按照一颗B+树进行排序,因此每张表只能拥有一个聚集索引。
在很多情况下,查询优化器非常倾向于采用聚集索引,因为聚集索引能够让我们在索引的叶节点上直接找到数据。
数据库索引为啥不用b树:
因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出)指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低;
什么时候使用B+树索引
一般的经验是对于访问表中很少一部分行时,使用B+树索引才有意义。
而对于像性别,地区,类型等字段,它们可取值的范围很小(低选择性),一般不推荐使用B+树索引;【此时一般用什么索引呢?】
反之,如果某个字段的取值范围很广,几乎没有重复(高选择性),则此时使用B+树索引是最合适的,例如email字段,在一些应用中通常都不允许重复出现。
因此,当访问高选择性字段并从表中取出很少一部分行时,对这个字段添加B+树索引是非常有必要的。
但是如果出现了访问字段是高选择性,但是取出的行数据占表中大部分的数据时,这时MySQL数据库就不会使用B+树索引了。
联合索引:对表上的多个列进行索引
覆盖索引:
从辅助索引中就可以得到查询的记录,而不需要查询聚簇索引中的记录,使用覆盖索引的好处是辅助索引不包含整行记录的所有信息,所以其大小要小于覆盖索引,因此可以大量减少IO操作
参考资料:
1.MySQL索引背后的数据结构及算法原理
http://blog.codinglabs.org/articles/theory-of-mysql-index.html