MySQL学习笔记

一、RDBMS和非RDBMS:

        1. RDBMS(关系型数据库):

  • 把复杂的数据结构归结为简单的二元关系,建立在关系模型基础上的数据库,表与表之间的数据记录有关系。

        2. 非RDBMS(非关系型数据库):

  • 基于键值对(不只有键值对)存储数据,性能非常高。

二、存储引擎:

        1. InnoDB:

  • InnoDB崩溃后可安全恢复

  • InnoDB是mysql的默认事物引擎,被设计用来处理大量的短期事务

  • InnoDB是为处理巨大数据量的最大性能设计

  • .frm:表的定义文件, .ibd:表的数据文件

        2. MyISAM:

  • MyISAM崩溃后无法安全恢复

  • 优势是访问速度快,对事物完整性没有要求或者以SELECT、INSERT为主的应用

  • .frm:存储表结构, .MYD:存储数据, MYI:存储索引

对比项MyISAMInnoDB
外键不支持支持
事务不支持支持
行表锁表锁,即使操作一条记录也会锁住整个表,不适合高并发的操作行锁,操作时只锁某一行,不对其他行有影响,适合高并发的操作
缓存只缓存索引,不缓存真实数据不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性影响
自带系统使用表YN
关注点性能:节约资源、消耗少、业务简单事务:并发写、事务、更大资源
默认安装YY
默认使用NY

        3. Archive:

  • 用于数据存档,仅支持插入(性能很高)和查询(性能较差)操作。拥有很好的压缩机制,使用zlib压缩库

        4. Blackhole:

  • 丢弃写操作,读操作会返回空内容。服务器会记录Blackhole表的日志,可用于复制数据到备库或者简单的记录到日志

        5. CSV:

  • 存储数据时,以逗号分隔各个数据项

        6. Memory:

  • 置于内存的表,同时支持哈希索引(默认)和B+索引

三、索引设计原则:

        1. 适合创建索引:

  • 字段的数值有唯一性的限制
  • 频繁作为WHERE查询条件的字段
  • 经常GROUP BY 和 ORDER BY的列

  • UPDATE、DELETE 的 WHERE 条件列
  • DISTINCT 字段
  • 多表 JOIN 连接操作, WHERE 条件 或是 用于连接的字段
  • 列的类型小的创建索引
  • 使用字符串前缀创建索引
  • 区分度高(散列性高)的列
  • 使用最频繁的列放在联合索引的左侧
  • 多个字段都要创建索引的情况下,联合索引优于单值索引

        2. 不适合创建索引:

  • 在 WHERE等条件中使用不到的字段
  • 数据量小的表不要使用索引

  • 有大量重复数据的列
  • 避免对经常更新的表创建过多的索引
  • 不建议用无序的值作为索引
  • 删除不再使用或者很少使用的索引
  • 不要定义冗余或重复索引

四、EXPLAIN分析语句:

列名描述
id在一个大的查询语句中每个SELECT关键字都对应一个唯一的id
select_typeSELECT关键字对应的那个查询类型
table表名
partitions匹配的分区信息
type针对单表的访问方式
possible_keys可能用到的索引
key实际用到的索引
key_len实际用到的索引长度
ref当使用索引列等值查询时,与索引列进行等值匹配的对象信息
rows预估的需要读取的记录条数
filtered某个表经过搜索条件过滤后剩余记录条数的百分比
extra一些额外的信息

        1. type:

  • 当表中只有一条记录,并且该表使用的存储引擎的统计数据是精确的,对该表的访 问方法是system

  • 当根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法是count
  • 在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方法进行 访问,则对该被驱动表的访问方法是eq_ref
  • 当通过普通二级索引列与常量进行等值匹配来查询某个表,对该表的访问方法可能 是ref
  • 当对普通的二级索引进行等值匹配查询,该索引列的值可能为NULL,那么对该表的 访问方法是ref_or_null
  • 单表访问方法时,在某些场景下可以使用’Intersection’、’Union’、’Sort-Union’这三种 索引合并的方式进行查询,该表的访问方法为index_merge
  • 针对一些包含’IN’子查询的查询语句中,如果查询优化器决定将’IN’子查询转换 为’EXISTS’子查询,而且子查询可以使用到主键进行等值匹配的话,该子查询的访问方 法为unique_subquery

  • 使用索引获取某些范围区间的记录,该表的访问方法可能是range
  • 当可以使用覆盖索引,但需要扫描全部的索引记录时,该表的访问方法为index

  • 全表扫描为all

        效率依次递减

        2. extra:

  • 当查询语句没有FROM子句时,会显示No table used

  • 当WHERE子句永远为FALSE时,会显示Impossible WHERE
  • 全表扫描来执行对某个表的查询,并且WHERE子句中有针对该表的搜索条件时,会 显示Using where

  • 使用索引访问来查询表(select *),若WHERE子句仅包含索引列的查询条件,会显示 NULL

  • 当查询语句有MIN或MAX聚合函数,但是没有符合WHERE字句中的搜索条件的记 录时,会显示 No matching min/max row;存在记录会显示Select tables optimized away
  • 当查询列表(select id)及搜索条件中只包含属于某个索引的列,会显示Using index
  • 索引条件下推会显示Using index condition
  • 在连接查询中,被驱动表不能有效的利用索引加快访问速度,mysql一般会为其分 配一块’join buffer’的内存块来加快查询速度(基于块的嵌套循环算法),会显示Using join buffer(hash join)
  • 在未使用索引的排序中,只能在内存中(记录较少)或者磁盘中(记录较多)进行排序, 此时会显示Using filesort
  • 在许多查询的执行过程中,mysql可能会借助临时表来完成一些功能,例 如’DISTINCT’、’GROUP BY’、’UNION’等子句,如果不能有效利用索引来完成查询,mysql 可能寻求通过建立内部的临时表来执行查询,此时会显示Using temporary

五、优化案例:

        1. 深翻页问题:

  • 查询过程中,若不是对主键进行查询,mysql会先走二级索引,获取结果后回表查询。而深翻页过程中,前面页码也会回表但之后数据会被丢弃,回表IO代价大,因此可以通过覆盖前面索引,只取需要的索引进行回表,随着数据量的增多,该优化效果愈发明显。其中,二级索引获取到的值只需取表中存在的(大部分情况下都存在id),也可以避免一次回表。

  • 例: select * from (select id from order_info where period = 202207 order by modified desc limit 99000, 1000) as temp join order_info where temp.id = order_info.id;

         2. 未走最优索引问题:

  • 查询过程中,存在二级索引,但mysql不一定会选择最优方式(视情况而定,可能走其他条件索引,或是走全表扫描),此时可以通过force index去强制索引。

  • 例:select * from order_info force index (idx_period) where period between 202205 and 202208 order by modified;

        3. 多条件查询问题:

  • 查询过程中,多个条件会一次走索引,期间会回表,此时可以增加联合索引,mysql会执行索引下推,减少不必要IO。由于联合索引需要存储更详细的数据,因此会消耗更多存储空间。

  • 例:alter table order_info add index idx_period_phone(period,phone);

  • Select * from order_info force index(idx_period_phone) where period > 202207 and phone > ‘997576’;

六、锁:

        1. 表锁:

                1)S、X锁:

锁类型自己可读自己可写自己可操作其他表他人可读他人可写
读锁否,等
写锁否,等否,等

                2)意向锁(intention lock):

  • 意向锁可理解为在进行行锁之后,对表锁做一个标记,并不是真锁

意向共享锁(IS)意向排它锁(IX)
意向共享锁(IS)兼容兼容
意向排它锁(IX)兼容兼容
意向共享锁(IS)意向排他锁(IX)
共享锁(S)兼容互斥
排它锁(X)互斥互斥

                3)自增锁(AUTO-INC):用于自增字段

                4)元数据锁(MDL):每执行一条DML、DDL语句时都会申请metadata锁,DML操作需要metadata读锁,DDL操作需要metadata写锁,metadata加锁过程是系统自动控制

        2. 行锁:

                1)记录锁(Record Locks):仅对该条记录上S或X锁

                2)间隙锁(Gap Locks):对查询未命中的记录时,会对该记录id的上下界开区间进行加锁(不区分S、X锁),不允许添加数据以解决幻读问题,但易出现死锁

                3)临键锁(Next-Key Locks):本质上是对记录锁与间隙锁的合体,既保护了该条记录,又能阻止别的事务将新纪录插入被保护记录的前边

                4)插入意向锁:执行插入操作时,总会检查当前插入操作的下一条记录(已存在的主索引节点)上是否存在锁对象,判断是否锁住了gap,如果锁住了,则判定和插入意向锁冲突,当前插入操作就需要等待,也就是配合上面的间隙锁或者临键锁一起防止了幻读操作

        3. 页锁:开销介于表锁和行锁之间,会出现死锁

        4. 乐观锁:适合读操作多的场景,相对来说写的操作比较少。优点在于程序实现,不存在死锁问题,但是阻止不了除了程序以外的数据库操作

        5. 悲观锁:适合写操作多的场景,因为写操作具有排他性。可以从数据库层面阻止其他事物对该数据的操作权限,防止”读-写”和”写-写”冲突,但是并发性差

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值