Perconna Server XtraDB 基于mysql innodb , 阿里基于percona原型加以修改
MariaDB
MyISAM 和 InnoDB是针对数据库表的;
慢查询的开启 记录
explain + 慢SQL分析
Show Profile 查询SQL在Mysql服务器中的执行细节和生命周期情况
默认是关闭的 set profiling = on
mysql>show profiles ;
show profiles 显示的信息:Query_ID ,Query (记录执行的sql ) ,Duration (执行时长)
mysql > show profile cpu ,block io , memory …… for query ‘id‘ (分解步骤详情,完整生命周期分析)
show profile for query 结果中 : 危险 status
convert HEAP to MyISAM (查询结果太大,内在不够用,往硬盘上转换了)
(create tmp table ,copy to tmp table ,remove tmp table ) 创建临时表
copy to tmp table on disk 临时表内存到硬盘
locked
全局日志 (general_log )
select * from mysql.general_log ; 收集sql日志 ,永远不要在生产环境开启这个功能
MySql数据库服务器的参数调优
以页为单位存储在磁盘上的 ,每页16k
表空间->段->n区(区是不连续的)->每个区下面有64个页 64*16 = 1M
页之间是双向链表 ,查询时根据key从根节点开始加载页到内存中去
页下面还有槽,再根据二分查询找到相应的数据
删除时 删除标记位
可能 1. 二叉树 2. 红黑树(平衡树) 3. hash 4 .B树 5. B+树
单纯的二叉树不是平衡的,可能两边高度相差很多
红黑树在数据量大的时候,树的高度也会越来越大,查询到叶子节点上的数据也就更加慢
hash查询是快 时间复杂度为O(1),但是不适应范围查询
B树是叶子节点的高度一致的 ,节点中的数据索引从左到右排列 ,不只是二叉的
B代表平衡,而非binary
B树叶子和非叶子都存数据,导致非叶子节点指针变少,树的高度增加。I/O操作变多,性能变低。
MySql的存储数据结构为B+树 (B树的变种)
树的高度 (h = 3 )
1)假设如下:
数据记录大小1KB
->叶子节点(页)可以存 16/1 = 16条数据
关键字和指针bigint 8B + 页指针6B
->非叶子节点可以存 16384/14 = 1170个对象(关键字-页指针)
2)高度为2和3的B+树
高度为2的B+树:1170 * 16 = 18720,约存2w条数据记录。
高度为3的B+树:1170 * 1170 * 16 = 21902400,约存2千万条数据记录。
所以:InnoDB中B+树的高度一般为1~3层。mysql查找一页时代表依次IO,通过主键索引只需要1~3次IO。
3)InnoDB表空间ibd文件中,约定page_no为3的,代表主索引的root page.
作者:沐兮_d64c
链接:https://www.jianshu.com/p/544e97672deb
B+树把data节点都移到叶子节点上了,非叶子节点上只存储索引 (可以放更多的索引)
叶子节点之前添加了指针(双向),增加了区间访问性能
mysql的innoDB默认的一个索引大节点的数据大小为16k show global status like ‘Innodb_page_size‘
InnoDB最小存储单位是页。16k,叶子节点和非叶子节点最小单位都是页。B+树中叶子节点存放数据(叶子节点间指针相连,适用于局部性原理),非叶子节点存放关键字+指针。
16KB的节点大小 可以存多少个索引 ?
InnoDB中
页指针6B,主键bigint占用8B
索引字段类型(主键)一般为bigint (8个字节)
再加上相邻两个元素之间保存的是下一个节点的指针(6个字节)
所以这个大节点能存储的 索引个数 = 16*1024 B / (8+6) = 1170 ;
假如一个data数据大小为1k , 可以存储多少索引元素
1170*1170 * 16 = 21902400 (2kw)
访问时先加载根节点到内存中去比对 ,根节点一般是常驻内存的
B树是一种平衡的多路查找(又称排序)树,在文件系统中有所应用。主要用作文件的索引。其中的B就表示平衡(Balance)
B+树有一个最大的好处,方便扫库,B树必须用中序遍历的方法按序扫库,而B+树直接从叶子结点挨个扫一遍就完了。
B+树支持range-query(区间查询)非常方便,而B树不支持。这是数据库选用B+树的最主要原因。
比如要查 5-10之间的,B+树一把到5这个标记,再一把到10,然后串起来就行了,B树就非常麻烦。B树的好处,就是成功查询特别有利,因为树的高度总体要比B+树矮。不成功的情况下,B树也比B+树稍稍占一点点便宜。
B树的优势是当你要查找的值恰好处在一个非叶子节点时,查找到该节点就会成功并结束查询,而B+树由于非叶节点只是索引部分,这些节点中只含有其子树中的最大(或最小)关键字,当非终端节点上的关键字等于给点值时,查找并不终止,而是继续向下直到叶子节点。因此在B+树中,无论查找成功与否,都是走了一条从根到叶子节点的路径。
有很多基于频率的搜索是选用B树,越频繁query的结点越往根上走,前提是需要对query做统计,而且要对key做一些变化。
另外B树也好B+树也好,根或者上面几层因为被反复query,所以这几块基本都在内存中,不会出现读磁盘IO,一般已启动的时候,就会主动换入内存。 mysql底层存储是用B+树实现的,因为内存中B+树是没有优势的,但是一到磁盘,B+树的威力就出来了。
B*树 是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;B树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2);
MyISAM
表锁
主键索引是非聚集索引,聚集型索引并不是一种单独的索引类型,而是一种存储方式,InnoDB 聚集型索引实际上是在同一结构中保存了 B+tree 索引和数据行。当有聚簇索引时,它的索引实际放在叶子页中。
. frm , .MYD, .MYI
B+树的结构存储的 ,叶子节点中 key为索引字段, value为硬盘文件地址 (存储在.MYI文件中)
再根据地址就从 .MYD文件中找到该记录 (这样就是跨文件查询)
MYISAM 不支持事务,也是它查询快的一个原因!
innoDB
支持行锁
数据和索引放在一块
记录数太少
经常增删改的字段
性别,籍贯 等差异率不高的情况 (选择性)
访问类型(8种值)
system > const > eq_ref > ref > fulltext > range > index > ALL
const 常量
eq_ref
唯一性索引扫描
ref
非唯一性扫描
range
in, > ,< , between
index
ALL
全表扫描
估算当前表有多少行被优化器查询到
根据表统计信息和索引使用情况,大致估算出找到目标记录所需查询的行数
越少越好
用覆盖索引解决 (select 的字段包含在所建立的索引中)
select * 时就用不到覆盖索引了
也会用到索引,但是它不是用来查找,而是用来排序
不会体现在ref信息中
像查询一样如果出现中断会发生 using filesort ,using temporary
group by
where 优先于having (能写在where条件中的就不要写到having中)
分组之前必排序,所以group by 索引原则也一致
可能会产生 临时表
如果GROUP BY 的列没有索引,产生临时表.
如果GROUP BY时,SELECT的列不止GROUP BY列一个,并且GROUP BY的列不是主键 ,产生临时表.
如果GROUP BY的列有索引,ORDER BY的列没索引.产生临时表.
如果GROUP BY的列和ORDER BY的列不一样,即使都有索引也会产生临时表.
如果GROUP BY或ORDER BY的列不是来自JOIN语句第一个表.会产生临时表.
如果DISTINCT 和 ORDER BY的列没有索引,产生临时表.
用了 SQL_SMALL_RESULT, mysql就会用内存临时表。
IN()只执行一次,它先查出B表中的所有id字段并缓存起来 ,再遍历和检查A.id和缓存的id
Hash join算法
1.确认小表是驱动表
2.确认涉及到的表和连接键分析过了。
3.如果在连接键上数据不均匀的话,建议做柱状图。
4.如果可以,调大hash_area_size的大小或pga_aggregate_target的值。
5.Hash Join适合于小表与大表连接、返回大型结果集的连接。
exists()会执行A.length次 (A为外表),它并不缓存exists()结果集,因为exists()结果集的内容并不重要 (true,false)
in是在内存里遍历比较( In-Memory Hash Join),也可能On-Disk Hash Join ,而exists需要查询数据库,所以当B表数据量较大时,exists效率优于in。
由于exists是用loop的方式,所以,循环的次数对于exists影响最大,所以,外表要记录数少,内表就无所谓了,而in用的是hash join,所以内表如果小,整个查询的范围都会很小,如果内表很大,外表如果也很大就很慢了,这时候exists才真正的会快过in的方式。
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。
所以无论那个表大,用not exists都比not in要快。
也就是说,in和exists需要具体情况具体分析,not in和not exists就不用分析了,尽量用not exists就好了。
数据库中的共享资源
冲突高,并发低,适合读
读锁
如果session1获取表t_a的读锁 lock table t_a read;
当前session可以查询该表,但是不能查询其它未锁定的表
Table ‘t_b‘ was not locked with LOCK TABLES
当前session不能更新锁定的表
Table ‘t_a‘ was locked with READ lock and can‘t be updated
其他sessioin也可以查询该表,也可以查询和更新其它未锁定的表
其他session插入更新会一直等待 (就是所谓的读阻塞)
直到session1 unlock tables
,其他session的更新操作才会提交
加写锁
mysql > lock talbe t_a write ;
当前session可以查询和更新锁定表
当前session不能查询其它未锁定的表
其他sessioin可以查询和更新其它未锁定的表
其它session不可以读和写session1写锁定的表 ,会阻塞
写锁会把其它session的读和写都阻塞
mysql5.5之前一直采用的是异步复制。主库的事务执行不会管备库的同步进度,如果备库落后,主库不幸crash,那么就会导致数据丢失。
MySQL在5.5中引入了半同步复制,主库在应答客户端提交的事务前需要保证至少一个从库接收并写到relay log中。那么半同步复制是否可以做到不丢失数据呢?
对于异步复制,主库将事务Binlog事件写入到Binlog文件中,此时主库只会通知一下Dump线程发送这些新的Binlog,然后主库就会继续处理提交操作,而此时不会保证这些Binlog传到任何一个从库节点上。
对于全同步复制,当主库提交事务之后,所有的从库节点必须收到,APPLY并且提交这些事务,然后主库线程才能继续做后续操作。这里面有一个很明显的缺点就是,主库完成一个事务的时间被拉长,性能降低。
对于半同步复制,是介于全同步复制和异步复制之间的一种,主库只需要等待至少一个从库节点收到并且Flush Binlog到Relay Log文件即可,主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全执行并且提交的反馈,这样就节省了很多时间。
字符串存储日期
datatime
timestamp
时间范围(1970-01-01 00:00:01 到 2038-01-19 03:14:07)
1 月 (30.44 天) 2629743 s
1年 (365.24 天) 31556736 s
31556736 x 68(年) + 18(天)x86400 = 2147413248
MySQL的timestamp类型,存储的是一个整型int数据,由于int是有大小范围的,最多存大约21亿(2147483648)的数据,所以timestamp存储的数据被限制在了1970~2038年之内。
unix stamp (绝对时间戳)
1970-01-01 00:00:01 到现在的秒数 bigint表示 unsigned
前端可以自定义格式
mysql : unix_timestamp
伪双活
同城双活
异地双活
原文:https://www.cnblogs.com/skystarry/p/14940719.html