Mysql基础操作
连接和关闭:mysql -u用户名 -p密码 -h主机地址 -P端口号
其他:\G,\c,\q,\s,\h,\d
InnoDB 表引擎
- 默认事务型引擎,最重要最广泛的存储引擎
- 数据存储到共享表空间,可以通过配置分开
- 对主键查询的性能高于其他类型的存储引擎
- 内部做了很多的优化,从磁盘读取数据时自动创建哈希索引
- 通过一些机制和功能支持真正的热备份
- 支持崩溃后的安全回复
- 支持行级锁
- 支持外键
MyISAM表引擎
- 拥有全文索引、压缩、空间函数
- 不支持事务和行级锁,不支持崩溃后的安全回复
- 表存储在两个文件 MYD和MYI
- 设计简单,某些场景下性能很好
其他表引擎
Archive、Blackhole、CSV
Mysql锁机制
基础概念:
表锁是日常开发中年常见的问题,因此是面试中最常见的考察点,当多个查询同一时刻进行数据修改时,就会产生并发控制问题
分为共享锁和排他锁
读锁
共享的,不堵塞,多个用户可以同时读取一个资源,互不干扰
写锁
排他的,一个写锁会阻塞其他的写锁和读锁,这样可以只允许一个人进行写入,防止其他用户进行的操作
锁粒度
表锁,系统性能开销最小,会锁定整张表,MyISAM
行锁,最大程度的支持并发处理,但是也带来了最大的锁开销InnoDB
事务处理
服务器层不管事务管理,由下层的引擎实现,所以一个事务中,使用多种存储引擎不靠谱
在非事务的表上执行事务操作Mysql不会提醒不会报错
存储过程
为以后的使用而保存的一条或者多条mysql语句的集合
存储过程就是有业务逻辑和流程的集合
可以在存储过程中创建表,更新数据、删除等等
使用场景::
通过把处理封装在容易使用的单元中,简化复杂的操作
保证数据的一致性
简化对变动的管理
触发器
提供给程序员和数据分析员来保证数据完整性的一种方法,他是与表事件相关的特殊的存储过程
使用场景:
通过数据库中的相关表实现级更改
实时健康空某张表的某个字段的更改而需要做出相应的处理
某些业务编号的生成
滥用会造成数据库以及应用程序的维护困难
MySQL索引
简单描述Mysql中索引,主键,唯一索引,联合索引的区别,对数据库的性能有什么影响?
Mysql索引的基础和类型:
索引类似于数据的目录,想要找到一本书的某个特定的主题,需要先查找书的目录,定位对应的页码
存储引擎使用类似的方式进行数据查询,先去索引中找到对应的值,然后根据匹配的索引找到对应的数据行
索引对性能的影响:
大大减小服务器需要扫描到数据量
帮助服务器避免排序和临时表
- 将随机I/O变为顺序I/O
- 大大提高查询速度,降低些的速度,占用磁盘
索引的使用场景
- 对于非常小的表,大部分情况下全表扫描效率更高
- 中到大型表,索引非常有效
- 特大型表,建立和使用索引的代价会随之增长,可以使用分区技术来解决
索引的类型
- 普通索引:基本的索引,没有任何的约束限制
- 唯一索引:与普通索引类型,但是具有唯一性约束
- 主键索引:特殊的唯一索引,不允许有空置
- 组合索引:将多个列组合在一起创建索引,可以覆盖多个列
- 外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作
- 全文索引:Mysql自带的全文索引只能用于MyISAM,并且只能对英文进行全文检索
主键索引和唯一索引的区别:
一个表只能有一个主键索引,可以有多个唯一索引
主键索引一定是唯一索引,唯一索引不是主键索引
主键可以与外键构成参照完整的约束防止数据不一致,唯一索引不可以
Mysql索引的创建原则:
- 最适合索引的列是出现在where子句的列,或者链接子句中的列,尾部是在select关键字后的列
- 索引列的技术越大,效果越好
- 对字符串进行索引,应该制定一个前缀长度,可以节省大量的索引空间
- 根据情况创建复合索引,复合索引可以提高查询效率
- 避免创建过多的索引,会占用额外的磁盘空间,降低写操作的效率
- 主键尽可能选择较短的数据类型,可以有效减少索引的磁盘占用
Mysql索引的注意事项:
复合索引遵循前缀原则
key(a,b,c)
where a= 1 and b = 2 and c = 3
where a= 1 and b = 2
where a = 1
where b = 2 and c = 3like查询,%不能在前,可以使用全文检索 where name like “%wang%” 索引不起作用
- column is null 可以使用索引
- 如果mysql估计使用索引的时间比全表扫描要慢,会自动放弃索引
- 如果or前的条件的列有索引,后面的没有,索引都不会被用到
- 列类型是字符串时,一定要加引号,否则索引会失效
Mysql的SQL语句编写考点
问题:有A(id,sex,par,c1,c2),B(id,age,c1,c2)两张表,其中A.id与B.id关联,现在要求写出一条SQL,将B中age>50的记录的c1,c2更新到A表统一记录中的c1,c2字段中
关联更新:
两种方式:
UPDATE A,B SET A.C1 = B.C1,A.C2 = B.C2 WHERE A.ID = B.ID
UPDATE A INNER JOIN B ON A.ID = B.ID SET A.C1 = B.C1,A.C2 = B.C2
答案:
update A,B set A.c1 = B.c1,A.c2 = B.c2 where A.id = B.id and B.age > 50;
update A inner join B on A.id = B.id SET A.c1 = B.c1,A.c2 = B.c2 where B.age > 50
六种关联查询:
- 交叉连接 cross join
select * from A,B,C
select * from A cross join B cross join C
没有任何的关联条件,结果是笛卡尔积,意义不大
- 内连接 inner join
select * from A,B where A.id = B.id
select * from A inner join B on A.id = B.id
多表中同事符合某种条件记录的集合,分为三类:
等值连接: ON A.id = B.id
不等值连接:ON A.id > B.id
自连接:select * from A T1 inner join A T2 ON T1.id=T2.pid
INNER JOIN 可以缩写成 JOIN
- 外连接
左外连接:LEFT OUTER JOIN 以左表位主,先查询出左表,按照ON后的关联条件匹配右表,没有匹配到的用NULL填充,可以简写为LEFT JOIN
右外连接:RIGHT OUTER JOIN 简写为 right join
- 联合查询
select from A UNION select from B UNION …
就是把多个结果集集中在一起,UNION前的结果为基准,需要注意的就是联合查询的列数要相等,相同的记录会合并
如果使用UNION ALL,不会合并重复行
- 全连接
Mysql 不支持全连接
可以使用left join和union和right join 联合使用
select from A left join B on A.id = B.id union select from A right join B on A.id = B.id
- 嵌套查询
用一条sql的结果作为另外一条sql语句的条件,效率不好把控,不建议使用
select * from A where id in (select id from B)
Mysql查询优化
项目中优化sql语句执行效率的方法,从哪些方面,sql语句性能如何分析?
- 查找分析查询速度慢的原因
- 优化查询过程中的数据访问
- 优化长难的查询语句
- 优化特定类型的查询语句
分析SQL查询慢的方法:
记录慢查询日志
分析查询日志,不要直接打开慢查询日志进行分析,这样比较浪费时间和精力,可以使用pt-query-digest工具进行分析
使用show profile
set profiling = 1 开启,服务器上执行的所有语句会检测消耗的时间,存到临时表中
show profiles;查看临时表
show profiles for query QUERY ID 查看某一条记录的具体时间分配
show status
show status 会返回一些计数器,show global status 查看服务器级别的所有计数
有时候根据这些计数,可以猜出哪些操作代价较高或者消耗时间较多show processlist
观察是否有大量的线程处于不正常的状态或者特使
explain
分析单条SQL语句,也可以使用desc 来达到一样的效果
desc select * from a
优化查询过程中的数据访问
- 访问数据太多当值查询性能下降
- 确定应用程序是否在检索大量超过需要的数据,可能是太多行或者列
- 确认Mysql服务器是否在分析大量不必要的数据行
避免使用如下SQL:
- 查询不需要的记录,使用limit解决
- 多表关联返回全部列,指定A.id,A.name
- 总是取出全部列,select * 会让优化器完成索引覆盖扫描
- 重复查询相同的数据使用缓存
是否在扫描额外的记录:
使用explain进行分析,如果发现查询需要扫描大量的数据但是只返回少数的行,可以通过以下技巧去优化:
使用索引覆盖扫描,把所有的列都放在索引中,这样索引不需要回标获取对应行就可以返回结果
修改表数据库和表的结构,修改数据表的范式
重写sql,让优化器可以以更优的方式执行
优化长难的查询语句:
mysql 内部每秒能扫描内存中上百万行数据,相比之下,响应数据给客户端就要慢的多
使用尽可能少的查询十号的,但是有的时候将一个大的查询分为几个小的查询也是有必要的
切分查询
将一个大的查询分为多个小的相同的查询,比如一次性删除1000万的数据要比一次删除1万,暂停一会儿的方案跟那个价损耗服务器的开销
分解关联查询
可以将一条关联语句分解成多条sql来执行
让缓存的效率更高
执行单个查询可以减少锁的竞争
在应用层做关联可以更容易对数据库进行拆分
优化特定类型的查询语句:
- 优化count()查询
count()中的 会忽略所有的列,直接统计所有的列数,因此不要使用count(列名)
myisam中,没有任何where条件的count(*)非常快
当有where条件时,myisam的count统计不一定比其他表引擎快
可以使用explain查询近似值,用近似值替代count(*)
增加汇总表
使用缓存
- 优化关联查询
确定on或者using自居的列上有没有索引
确保group by 和order by 中只有一个表的列,这样才有可能使用索引
优化子查询
用关联查询替代
优化group by和distinct
这两种查询均可以使用所索引来优化,是最有效的优化方法
关联查询中,使用标识列进行分组的效率会更高
如果不需要order by,进行group by时使用 order by null ,mysql不会再进行文件排序
with rollup超级聚合
- 优化limit分页
limit偏移量大的时候,查询效率较低
可以记录上次查询的最大ID,下次查询时直接根据该ID来查询
- 优化union查询
union all 的效率高于union,去重放到应用层去解决
首先说明如何定位低效sql
根据sql语句可能低效的原因做排查,从索引着手,考虑数据访问的问题,长难句的问题,特定类型优化的问题
Mysql高可扩展和高可用
简述mysql分表操作和分区的工作原理,分别说说分区和分表的使用场景和各自的优缺点
分区表的原理
对用户而言,分区表是一个独立的逻辑表,但是底层Mysql将其分层了多个物理子表,这对用户来说是透明的,每一个分区表都会使用一个独立的表文件
创建表的时候使用partition by 子句定义每个enquiry存放的数据,执行查询的时候,优化器会根据分区定义过滤哪些没有我们需要数据的分区,这样查询只需要查询所需数据在的分区既可
主要目的是将数据按照一个较粗的粒度分在不同的表中,这样可以将相关的数据放在一起,而且如果想一次性删除整个去的数据也很方便
适用场景:
- 表非常大,无法全部存在内存,或者旨在表的最后有热点数据,其他都是历史数据
- 分区表的数据更易维护,可以对独立的分区进行独立的操作
- 分区表的数据可以分布在不同的及其上,从而高效利用资源
- 可以使用分区避免某些特殊瓶颈
- 可以备份和恢复独立的分区
限制:
- 一个表中只能有1024个分区
- 5.1版本中,分区表表达式必须是证书,5.5可以使用列分区
- 无法使用外键
- 需要对现有表的结构进行修改
- 所有分去都必须使用相同的存储引擎
- 分区字段中如果有主键和唯一索引列,那么主键列和唯一列都必须包含进来
- 分区函数中可以使用的函数和表达式有一定的限制
- 某些存储引擎不支持分区
- 对于myisam分区表不能使用load index to cache
- 对于myisam使用分区表时需要打开更多的文件描述符
分库分表的原理
通过一些hash算法或者工具实现将一张数据垂直或者水平进行物理切分
使用场景:
- 单表记录的数据达到百万或者千万
- 可以解决表锁的问题
分表方式:
- 水平分割
表很大,分割后可以降低在查询时需要读取的数据和索引的页数,同时也降低了索引的层数,提高查询速度
使用场景:表中的数据本身就有独立性,例如表中分别记录各个地区的数据或者不同时期的数据,也别是有数据常用,有些不常用
需要把数据存放在多个介质上
缺点:
- 给应用增加复杂度,通常查询时需要多个表名,查询所有数据都需要unoin操作
- 在许多数据库应用中,这种负责性会超过它带来的有点,查询时会增加读取一个索引层的磁盘次数
垂直分表:
把主键和列放在不同的表中
使用场景:
- 一个表中某些列常用,有些不常用
- 可以使数据量变小,一个数据页能存储更多的数据,查询时减少I/O次数
缺点:
管理冗余列,查询所有的数据需要join操作
整体缺点:有些分表的策略基于应用层的逻辑算法,一旦逻辑算法改变,整个分表逻辑都会改变,不易于扩展
对于应用层来说,逻辑算法会增加开发成本
Mysql复制原理和负载均衡
在主库上把数据更改记录到二进制日志
从库将主库的日志复制到自己的中继日志中
从库读取中继日志中的事件,将其放在自己的库中执行
解决的问题:
数据分布:随意停止或者开始复制,并在不同地理位置分布数据备份
负载均衡:降低单个服务器的压力
高可用和故障切换:帮助应用程序避免单点失败
升级测试:可以使用更高版的Mysql作为从库
设定网站的用户数据量在千万级,但是活跃用户的数据量只有1%,如何通过优化数据库提高用户的访问速度?
Mysql安全性考点
SQL语句应该考虑哪些安全性问题
SQL查询的安全方案
- 使用预处理语句防SQL注入
- 写入数据库的数据要进行特殊字符的转义
- 查询错误信息不要返回给用户,将错误记录到日志
Mysql其他安全设置
- 定期做数据备份
- 不给查询用户root权限,合理分配权限
- 关闭远程访问数据库权限
- 修改root口令
- 删除多余用户
- 修改root用户名称
- 限制一般用户浏览其他库
- 限制用户对数据文件的访问权限