高性能MySql读书笔记

以下是Xmind笔记,看着有些费劲。。。记录下

高性能Mysql
    mysql架构和基础
        mysql逻辑架构图
            客户端
            服务器层
                连接/线程处理、查询缓存、解析器、优化器
            存储引擎
        锁粒度
            表锁:服务器会为诸如 alter Table之类语句使用表锁,而忽略存储引擎的锁机制
            行级锁:只在存储引擎层,不在服务器层
        事务
            ACID
                atomicity 原子性
                consistency 一致性
                isolation 隔离性
                durability 持久性
            隔离级别
                Read uncommitted
                Read  committed
                Repeatable read  (mysql默认)
                Serializable 可串行化
            死锁
                InnoDB 处理方法:将持有最少行级排它锁的事务进行回滚
            服务器层不管理事务,是由下层的存储引擎实现的。  最好不要在事务中混合使用存储引擎(InnoDB-事务型、MyIsAM-非事务型)
        MVCC 多版本并发控制
            在每条记录后保留2条隐藏的列:行版本号、行删除版本号。每开始一个事务,系统版本号自动递增。Select:只查 【 行版本号<=当前系统版本号 && 行删除版本要么未定义,要么大于当前系统版本号--确保未被删除】。
        存储引擎
            InnoDB (mysql默认)
                事务型、高并发  间隙锁、聚簇索引、热备份
            MyIsAM
                不支持事务(没有回滚)、不支持行级锁、不支持崩溃后的安全恢复
                对整张表加锁
                对于只读数据可以考虑
        导入导出
            Create table a Like b; Insert into a  Select * from b;
    Schema与数据类型优化
        数据类型
            整数类型: -2^(N-1)到2^(N-1)-1.  Unsigned。INT(11) 指定宽度,只是规定了交互工具(mysql命令行客户端)来显示字符的个数,值的合法范围,比如INT(1)和INT(20)是相同
            实数类型:DECIMAL ,数据量大时也可以用BIGINT代替
            字符串类型
                VARCHAR 可变长字符串、CHAR 定长,括号里的是字符数
                ENUM 枚举代替字符串类型
            日期和时间类型:TIMESTAMP(1970年-2038年) 效率更高、DATATIME(1001年-9999年)
            IPv4地址:32位无符号整数,不是字符串
        范式和反范式
            第一范式:无重复的列
            第二范式:属性完全依赖于主键
            第三范式:属性不依赖于其他表的非主键
            反范式可以避免表关联,所以一般是 混用范式和反范式
        缓存表与汇总表
            缓存表:存储从其他表获取速度慢的信息,例如 逻辑上冗余的数据
            汇总表:保存 Group By语句聚合数据,例如 逻辑上不冗余的数据
        总结
            一切为了  更快地读,更慢地写
            尽量使用可以正确存储数据的最小数据类型
            尽量 NOT NULL
    索引
        索引类型
            BTREE,InnoDB使用B+Tree,通过比较节点页的值和要查找的值找到合适的指针进入下层子节点(二分查找),有序的
            哈希索引:对索引列计算一个哈希码
                InnoDB有 自定义哈希索引:当注意到某些索引列被使用得非常频繁时,它会在内存中基于BTree索引之上再创建一个哈希索引,自动的内部行为
                创建自定义哈希索引
                    新增一个被索引的url_crc 列
                    Select id From url Where url_crc=CRC32("http://myslq.com")  And url="http://myslq.com";
                无法排序、不支持部分索引列匹配查找、不支持范围查询
        索引策略
            独立的列:索引列不能是表达式的一部分,也不能是函数的参数
            前缀索引
                索引开始的部分字符,提高索引效率。对于BLOB、Text、很长的VARCHAR,必须使用前缀索引
                索引的选择性:不重复的索引值(基数)/数据表的记录总数(#T),1/#T到1之间,例如 唯一索引的选择性=1     --P154
                无法Order By 和Group By,无法覆盖扫描
            多列索引
                在多个列上建立独立的单列索引大部分情况下不能提高mysql的查询性能
                Or  -> UNION ALL
                选择合适的索引列顺序:当不需要考虑排序和分组时,将选择性最高的列放在前面通常是最好的
            聚簇索引 (InnoDB)
                数据存储方式,表示数据行和相邻的键值紧凑地存储在一起。一般 一个表只能有一个聚簇索引
                叶子页包含了行的全部数据,但是节点页只包含了索引列
                缺点: 二级索引访问需要俩次索引查找。 存储引擎需要找到二级索引的叶子节点获得对应的主键列,然后根据这个值取聚簇索引中查找到对应的行
                聚簇索引:主键索引,非聚簇索引:二级索引    --P167
            主键索引:Auto_Increment
                并发插入 可能导致间隙锁竞争  ,innodb_autonic_lock_mode配置=0:锁,保证ID连续; >=1: 性能提升,ID可能不连续
            覆盖索引
                定义:一个索引包含所有需要查询的字段的值
                由于InnoDB的聚簇索引,覆盖索引对InnoDB表非常有用:若二级主键能覆盖查询,则可以避免对主键索引的二次查询。
                延迟关联:  P174、P187
                    Select name,sex From profiles Where sex='M' Order By rating Limit 100000,10
                    转化为 Select name,sex From profiles Inner Join( Select id From profiles where x.sex='M' Order By rating Limit 100000,10) As x  Using(id);
            索引扫描来做排序
                EXPLAIN出来的type列:"index"
                若索引不能覆盖查询所需的列,按索引顺序读取的速度通常要慢于顺序全表扫描,因为 每扫描一条索引都得回表查询
                OrderBy 索引最左前缀
                查询需要关联多表,则只当OrderBy子句所引用的字段全部为第一个表时,才能使索引用作排序
        总结
            BTree索引的限制
                最左前缀
                不能跳过索引的列
                若查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找
            mysql 不能在索引中执行LIKE操作
            只在索引中做最左前缀匹配的LIKE比较,若是通配符开头的LIKE查询,将无法匹配
            尽量扩展已有索引而不是创建新索引,但有时出于性能考虑需要冗余索引
            id > 45  转化为  id IN (1,4,99) :范围条件查询,就无法使用范围列后面的其他索引列,但是对于多个等值查询就可以
    查询性能优化
        慢查询
            是否向数据库请求了不需要的数据? LIMIT、只取需要的列
            是否在扫描额外的记录? 
“Extra: Using Where”: Mysql将通过Where条件来筛选存储引擎返回的记录
                索引中使用where 是在存储引擎层完成
                索引覆盖扫描(Extra:Using index)直接从索引中过滤不需要的记录并返回命中结果,无须再回表查询,Mysql服务器层完成
                Using Where 需要先从数据表读出记录然后过滤,Mysql服务器层完成
        重构查询方式
            大查询分解成多个小查询
            分解关联查询
                让缓存的效率更高:关联中的某个表变化,就无法使用查询缓存,
拆分后,某个表很少变化可重复利用查询缓存结果
        查询的过程 -图P204
            mysql客户端/服务端通信协议
                半双工,要么服务器向客户端发数据,要么客户端到服务器, 俩个动作不能同时发生
                库函数实际是从缓存获取数据
                查询状态   -P207
            查询缓存
                查询优化器
                    静态优化:直接对解析树分析优化,第一次完成后一直有效,编译时优化
                        Or -> IN()先对列表内数据排序,再二分查找,O(log N)优于O(N)
                    动态优化
                关联查询 :嵌套循环关联
                    先在一个表循环取出单条数据,再嵌套循环到下一个表寻找匹配的行,直到找到所有表的匹配的行为止,然后回溯到上一个表
                    关联查询优化器 评估不同顺序的成本来选一个代价最小的关联顺序
                排序优化 不能用索引生成排序结果时,需自己排序(filesort)
                    俩次传输排序 , I/O成本高
                    单次传输排序,当查询需要所有列的总长度不超过参数
max_length_for_sort_data ,Mysql使用此排序算法。
            查询执行引擎
                逐步执行计划
            返回结果给客户端
                增量、逐步返回的过程
        查询优化器的局限性
            糟糕:Where条件中包含IN()的子查询语句
                Select * From film Where film_id IN(
Select film_id From film_actor Where actor_id = 1)
                转化为 
 Select film.* From film inner Join film_actor Using(film_id) Where actor_id = 1
            UNION
                Union的各个子句中分别使用这些 Order By、Limit
        优化特定类型查询
            Count
                count(列值):不统计列值NULL
                最好用Count(*)
            优化关联查询
                确保Group By和Order By只涉及到一个表中的列,这样索引才可以优化
            优化子查询
                尽量用关联查询代替
            优化Limit 分页
                延迟关联 -见上一章
            优化UNION查询
                创建并填充临时表来执行Union查询; 尽量用Union All,否则会对整个临时表做唯一性检查,代价高
            使用用户自定义变量
                Set @rownum := 0; 
Select id,@rownum := @rownum + 1 AS rownum From actor
        总结
            分组查询:若可以,在应用程序中做超级聚合更好
            快速地完成事情:尽量使用Update 代替先Select For Update再Update的写法,因为事务提交的越快,持有锁的时间越短
            尽量少做事:看是否真的需要这么精确的计算,可以运用简单的方案过滤大多数数据
    高级特性
        分区表  (粗粒度)
            定义:是一个独立的逻辑表,但是底层由多个物理子表组成。底层表必须相同存储引擎
            CREATE TABLE sales(
    order_date DATETIME NOT NULL,
    -- other columns omitted
)ENGIN=InnoDB PARTITION BY RANG(Year(order_date))(
    PARTITION p_2010 values less than (2010),
    PARTITION p_2010 values less than (2010),
    PARTITION p_2010 values less than (2010),
    PARTITION p_catchall values less than MAXVALUE );,
                表达式返回的值是一个确定的整数,且不能是常数
            策略
                全量扫描数据,不要任何索引(根据分区的规则大致定位需要的数据位置)
                索引数据,并分离热点  (数据有明显的热点,可以单独放一个分区)
            可能的问题
                Null值会使分区过滤无效
                    PARTITION BY RANGE COLUMNS(order_date)  
--直接使用列本身而不是基于列的函数,mysql5.5版本
                尽量分区列和索引列匹配
                限制分区的数量,一般最多100个左右分区
            总结
                要做Where条件带入分区列!!!
                根据粗粒度索引优势,通过分区过滤通常可以让查询扫描更少的数据。
        视图
            本身是一个虚拟表,不存放任何数据,返回的数据是从其他表中生成的
            CREATE VIEW Oceania AS 
    Select * from country where continent = 'Oceania'
    With CHECK OPTION;
            合并算法、临时表算法(包含Group By、Distinct、聚合函数、Union、子查询)
            不支持在视图上建触发器
            只有合并算法的视图 才可更新。
(update Oceania Set population = popluation * 1.1 Where Name='Australia')
        存储过程
            适用于:   相比查询执行的成本,解析和网络开销很明显
        触发器
            每个表的每个事件,最多只能定义一个触发器
            基于行的触发
            作用: 实现更新反范式化数据、记录数据变更日志、系统维护任务、约束
        事件
            指定mysql 在某个时候执行一段代码,或者每隔一段时间间隔执行一段代码
        绑定变量
            SET @sql := 'Select id,first_name  FROM actor where first_name=?';
            客户端向服务器发送一个 sql 语句原型,服务器解析并存储这个 sql 部分执行计划,返回客户端处理句柄。以后每次执行这类查询,客户端都指定使用这个句柄。
        字符集和校对规则
            一种从二进制编码到字符的映射;  校对: 用于字符集的排序规则
            服务器 -> 数据库 -> 表,这是一个逐级继承的默认设置,最靠底层的默认设置影响
            大小写敏感:_cs  、_ci (case sensitive;  case insensitive);
 字符串编码的二进制:_bin
                col2 CHAR(1) CHARSET utf8,
col3 CHAR(1) COLLATE latin1_bin
            只有排序查询要求的字符集与服务器数据的字符集相同的时候,才能使用索引进行排序
        全文索引 (B-Tree)
            通过关键字匹配来进行查询过滤,基于相似度的查询
            只有MyISAM 支持全文索引,msql5.6版本后,InnoDB 也支持了
            自然语言的全文索引
                在整个索引中出现次数越少的词语,匹配时的相关度就越高
                SELECT film_id,title, RIGHT(description,25)
From film_text
Where MATCH(title,description)   AGAINST('factory casu');
                自动按照相似度进行排序
            布尔全文索引
                SELECT film_id,title, RIGHT(description,25)
From film_text
Where MATCH(title,description)   AGAINST('+factory  +casu'  IN  BOOLEAN MODE);
                只有MyISAM 引擎才能使用
        查询缓存
            定义:缓存完整的select 查询结果
            默认应该关闭查询缓存;
若实在查询缓存作用很大,也要配置很小的查询缓存空间(几十兆)
            若查询语句包含任何不确定的函数,那么查询缓存不能找到缓存结果。如:current_date
            命中和写入的比率,Qcache_hits/Qcache_inserts >3:1  通常查询缓存是有效的;即缓存带来的资源节约大于其本身的资源消耗;
            Flush query cache: 碎片管理。小心用,因为无法访问查询缓存,服务器会僵死一段时间。
            query_cache_size  设置成0, 来关闭查询缓存。
            总结:
                对于写密集型应用,直接禁用  可以提高系统性能

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值