PHP面试考点---13.mysql考察点

1. 数据类型

int(0) 整形,0代表最小宽度,用于填充

Char(16) 定长字符串,16代表长度,超过16的会被截断,不够16时空格填 充

Varchar(16) 变长字符串,16代表长度,超过16的会被截断,不够16时缩小长 度,不超过255时使用1个字节储存长度,超过255使用2个字节

Decimal(5,2) 存储大数值,5长度,2小数位数

 

2. 基本操作

数据库连接:mysql -u -p -h -P

\G 格式化显示

\c 取消命令

\q 退出mysql

\s 显示mysql服务器的状态

\h 帮助信息

\d 改变执行符号  ;号改成别的

 

3. 表引擎

Innodb: 默认事务型引擎, 性能非常优秀, 应用最广泛

数据存储在共享表空间, 可以通过配置分开.

对主键查询的性能高于其他引擎

内部做了很多优化, 从磁盘读写时自动在内存构建hash 索引,插入时自动构建插入缓冲区

通过一些机制和工具支持真正的热备份

支持崩溃后的安全恢复

支持行级锁

支持外键

Myisam: 5.1前是默认mysql存储引擎;

拥有全文索引/压缩/空间函数

不支持事务和行级锁, 不支持崩溃后的安全恢复

表存储在两个文件, myd和myi

设计简单, 某些场景下性能很好 比如select *

4. 其他表引擎

Memory, CSV

 

5. 锁机制

表锁手势日常开发当中常见的问题, 因此也是面试中最常见的考察点, 当多个查询同一时刻进行数据修改时, 就会产生并发控制的问题.

共享锁和排他锁, 其实就是读锁和写锁

读锁

共享的,不堵塞, 多个用户可以同时读一个资源, 互不干扰

写锁

排他的, 一个写锁会堵塞其他的写锁和读锁, 这样可以只允许一个人进行写入, 防止其他用户读取正在写入的资源.(作用是为了防止用户在读取正在更新的资源时误以为当前的就是最新的, 还有就是防止两个人同时对同一资源修改时改乱资源)

锁粒度

表锁,, 系统性能开销小, 会锁定整张表, myisam使用表锁

行锁, 最大粒度的支持并发处理, 但是也带来了最大的锁开销, innodb实现行级锁

 

6. Mysql的事务处理

Mysql提供事务处理的表引擎innodb

服务器层不管理事务, 由下层的引擎实现, 所以同一个事务中,使用多个存储引擎是不靠谱的

在非事务的表上执行事务操作mysql不会发出提醒, 也不会报错, 效果也不会成功

 

7. Mysql的存储过程

存储过程:

为以后的使用而保存的一条或多条myql语句的集合

存储过程就是有业务逻辑和流程的集合

可以在存储过程中创建表,更新数据, 删除等等

使用场景:

通过把处理封装在容易使用的单元中,简化复杂的操作

保证数据的一致性

简化对变动的管理

 

8. Mysql触发器

触发器:

提供给程序员和数据分析员来保证数据完整性的一种方法, 它是与表事件相关的特殊的存储过程

应用场景:

可以通过数据库中的相关表实现级联更改

实时监控某张表中的某个字段的更改而需要做出相应的处理

 

9. mysql索引的基础和类型:

索引的基础:

索引类似于数据的目录, 要想找到一本数的某个特定主题, 需要先查找书的目录, 定位对应的页码

存储引擎使用类似的方式进行数据查询, 先去索引当中找到对应的值, 然后根据匹配的索引找到对应的数据行

索引对性能的影响:

大大减少服务器需要扫描的数据量

帮助服务器避免排序和临时表

将随机i/o变顺序i/o

大大提升查询速度, 降低写的速度, 占用磁盘

索引的使用场景:

对于非常小的表,大部分情况下全表扫描效率更高

中大型表, 索引非常有效

特大型的表, 建立和使用索引的代价将随之增长, 可以使用分区技术来解决

索引的类型:

索引有很多种类型, 都是实现在存储引擎层的

普通索引:最基本的索引, 没有任何约束限制

唯一索引:与普通索引类似, 但是具有唯一性约束

主键索引:特殊的唯一索引, 不能为空

一个表只能有一个主键索引, 可以有多个唯一索引,

主键索引是唯一索引, 唯一索引不是主键索引

主键可以与外键构成参照完整性约束, 防止数据不一致

组合索引: 将多个列组合在一起创建索引, 可以覆盖多个列

外键索引: 只有innodb类型的表才可以使用外键索引, 保证数据的一致性,完整性和实现级联操作

全文索引: mysql自带的全文索引只能用于myisam,并且只能对英文检索

 

10. Mysql索引的创建原则

原则:

1. 最适合索引的列是出现在where子句中的列, 或连接子句中的列而不是出现在select关键字后的列

2. 索引列的基数越大, 索引的效果越好

3. 对字符串进行索引, 应该制定一个前缀长度, 可以节省大量的索引空间

4. 根据情歌创建符合索引, 符合索引可以提高查询效率

5. 避免创建过多的索引, 索引会额外占用磁盘空间, 降低写操作效率

6. 主键尽可能选择较短的数据类型, 可以有效减少索引的磁盘占用, 提高查询效率

注意:

1. 复合索引遵循前缀原则

Key(a,b,c)

Where a=1 and b=2 and c=3 ✔

Where a=1 and b=2 ✔

Where a=1 ✔

Where b=1 and c=2 ✖

Where b=1 ✖

Where a=1 and c=2 ✖

复合索引要按照顺序使用才能生效

2. Like查询, %不能在前, 可以使用全文索引

3. Column is null 可以使用索引

4. 如果mysql认为索引更慢的时候会放弃索引

5. 如果or前的条件列有索引, 后面的没有, 索引不会被用到

6. 列类型是字符串, 查询一定要给值加引号, 否则索引失效

 

11. Mysql的语句编写考点

1.真题:有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 join b on a.id=b.id set a.c1=b.c1, a.c2=b.c2 where b.age>50;

Update a,b set a.c1=b.c1, a.c2=b.c2 where b.age>50;

 

2.关联查询语句

六中关联查询: 交叉连接(CROSS JOIN), 内连接(INNER JOIN), 外连接(LEFT/RIGHT JOIN), 联合查询(UNION与UNION ALL), 全连接(FULL JOIN)

交叉连接

Select * from a,b(,c)或者

Select * from a cross join b (cross join c)

内连接

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

外连接

左外连接: left outer join, 以左表为主, 先查询出左表, 按照on后的关联条件匹配右表, 没有匹配到的用null填充, 可以简写成left join

右外连接: right outer join, 以右表为主, 先查询出右表, 按照on后的关联条件匹配左表, 没有匹配到的用null填充, 可以简写成right join

联合查询

Select * from a union seelect * from b union ...

就是把多个结果集集中在一起, union前的结果为基准, 需要注意的是联合查询的列数要相等, 相同的记录行会合并

如果使用unoin all不会合并记录,但是速度回慢于unoin

全连接

Mysql不支持全连接, 可以使用left join和unoin和right join 联合使用

嵌套查询

用一条sql语句的结果作为另一条sql语句的条件(不建议使用, 因为查询速度不好把控)

Select * from a where id in (selelct id form b)

 

解题方法:

根据考题要搞清楚表的结构和多表之间的关系, 根据想要的结果思考那种关联方式, 通常把要查询的列先写出来, 然后分析这些列属于那些表, 才考虑使用关联查询

 

真题: 为了记录足球比赛的结果, 设计表如下:

Team: 参赛的队伍表

 

Match: 赛程表

 

其中, match赛程表中的hostTeamID与guestTeamID都和team表中的teamID关联, 查询2006-1-1到2006-2-1之间的所有比赛, 并且使用以下形式列出: 拜仁 2:0 不莱梅 2006-1-2

Select t1.teamName, m.matchResult, t2.teamName, m.matchTime from match m left join team t1 on m.hostTeamID=t1.teamID, left join team t2 on m.guestTeamID=teamID where m.matchTime >’2016-1-1’ and m.matchTime<’2016-2-1’;

 

12. Mysql的查询优化

真题: 请简述项目中优化sql语句执行效率的方法, 从哪些方面, sql语句性能如何分析?

1. 查找分析速度慢的原因

记录慢查询日志

分析查询日志, 不要直接打开慢查询日志进行分析, 这样比较浪费资源时间和精力, 可以使用pt-query-digest工具进行分析

 

2. 优化查询过程中的数据访问

使用show profile

Set profiling=1; 开启, 服务器上执行的所有语句会检测消耗的时间, 存在临时表中

Show profiles

Show profile for query 临时表ID

mysql> set profiling=1;

mysql> select * from articles;

mysql> show profiles;

mysql> show profile for query 1; //1是临时表id

使用show status

Show status 会返回一些计数器, show global status 查看服务器级别的所有计数

有时根据这些计数, 可以猜出那些操作代价较高或消耗时间多

使用show processlist

观察是否有大量线程处于不正常的状态或者特征

* 使用explian

分析单条sql语句

Explian select * from user; 或者 desc select * from user; 结果是一样的

 

访问数据太多导致性能下降

确定应用程序是否在检索大量超过需要的数据, 可能是太多行或列

确定mysql服务器没有在处理一些不必要的数据行

避免使用如下sql语句

查询不需要的记录, 使用limit解决

多表关联返回全部列, 指定a.id, a.name, b.age

使用select * ,指定where条件

重复查询相同的数据, 可以缓存数据, 下次直接读取缓存

是否在扫描额外的记录

使用explain来进行分析, 如果发现查询需要扫描大量的数据但是只返回少数行, 可以通过如下技巧优化:

使用索引覆盖扫描, 把所有用的列都放到索引中, 这样存储引擎不需要回表获取对应的行就可以返回结果

 

改变数据库和表的结构, 修改数据表范式. 比如我们要关联查两张表, 但是第二张表只用到了一个字段那么就可以把那个字段冗余到第一张表里, 用空间来换取时间已达到提高查询效率

重写sql语句, 让优化器可以更优的方式执行查询, 比如优化那些没有使用到索引的sql语句

 

3. 优化长难的查询语句

一个复杂查询还是多个简单查询

Mysql内部每秒能扫描内存中上百万行数据, 相比之下响应数据给客户端就要慢得多

使用尽可能少的查询是好的, 但是有时将一个大的查询分解成多个小的查询也是有必要的, 小的查询可以更方便的做缓存

切分查询

将一个大的查询分分为多个小的相同的查询, 比如一次删除1000万条数据服务器开销是非常大的, 而且在删除的时候会锁表, 我们就可以查分成一次删除一万条暂停一会再执行下一次

分解关联查询

可以将一条关联语句分成多条sql来执行

让缓存的效率更高

执行单个查询可以减少锁的竞争

在应用层做关联可以更容易对数据库进行拆分

查询效率会大幅提升

冗余查询会少

 

4. 优化特定类型的查询语句

优化count()查询

Count(*)中的*会忽略所有的列, 直接统计所有行数, 因此不要使用count(别名)

Myisam中, 没有任何where条件的count(*)是非常快的, 但是加了where之后就不一定比其他表引擎快

可以使用explain查询近似值, 用近似值替换count(*)

增加汇总表, 数据改变了修改汇总表就可以了

使用缓存

优化关联查询

确定on或者using子句的列上有索引, 没有索引的话会全表扫

确保group by和order by中只有一个表中的列, 这样mysql才有可能使用索引

优化子查询

使用关联查询来替代

优化group by和distinct

这两种查询使用索引来优化, 是最有效的优化方法

关联查询中, 使用标识列(主键列,和自增列)进行分组的效率会更高

如果group by之后不需要排序要使用group by null不然会进行排序导致效率消耗

With rollup超级聚合, 可以挪到应用程序中处理

优化limit分页

Limit偏移量大的时候, 查询效率较低

可以记录上一次查询的最大id, 下次查询直接根据id来进行查询, 这样查询虽然不一定绝对准确,但是降低查询的损耗.

优化union查询

使用union all优化union, union all会把所有的数据查询出来, 重复的数据可以在应用层中处理

解题方法

对于此类考题, 先说明如何定位抵消sql语句(使用show profilelist, show status定位), 然后根据sql语句可能抵消的原因做排查(使用explian分析单条语句),先从索引着手, 如果索引没有问题, 考虑以上几个方面, 数据访问的问题, 长难询句的问题还是一些特定类型优化的问题, 逐一回答

 

真题:

Sql语句优化的一些方法

 

13. Mysql的高可扩展和高可用

真题 : 简述mysql分表操作和分区的工作原理, 分别说说分区和分表的使用场景和各自有缺点

1. 分区表的原理

工作原理: 对用户而言, 分区表是一个独立的逻辑表, 但是底层mysql将其分成了多个物理子表, 这对用户来说是透明的, 每一个分区表都会使用一个独立的表文件

创建表时使用partition by子句定义每个分区存放的数据, 执行查询时, 优化器会根据分区定义过滤那些没有我们需要数据的分区, 这样查询只需要查询所需要数据所在的分区即可

分区的目的是将数据按照一个较粗的粒度分在不同的表中, 这样可以将相关的数据存放在一起, 而且如果想一次性删除整个分区的数据也是很方便

使用场景:

(1) 表非常大, 无法全部存在内存, 或者只在表的最后有热点数据, 其他都是历史数据

(2) 分区表的数据更易维护, 可以对独立的分区进行独立的操作

(3) 分区的数据分布在不同的服务器上, 可以更好的利用资源

(4) 可以使用分区表来避免某些特殊的瓶颈

(5) 可以备份和恢复分区

限制:

(1) 一个表最多分1024个分区

(2) 5.1版本中, 分区表表达式必须是整数, 5.5可以使用列分区

(3) 分区字段中如果有主键和唯一索引列, 那么主键列和唯一列都必须包含进来

(4) 分区表不能使用外键约束

(5) 需要对现有的表结构进行修改

(6) 所有分区都必须使用相同的存储引擎

(7) 分区函数中可以使用的函数和表达式会有一些限制

(8) 某些存储引擎不支持分区

(9) 对于myisam的分区表, 不能使用load index into cache

(10) 对于myisam表, 使用分区表时需要打开更多的文件描述符

 

 

2. 分库分表的原理

通过一些hash算法或者工具实现将一张数据表垂直或水平分开

使用场景:

(1) 单表记录条数达到百万到千万级别时

(2) 解决表锁的问题

分表方式:

(1) 水平分割: 表很大, 分割后可以降低在查询时需要读的数据和索引的页数, 同 时降低了索引的层数,提高查询速度

使用场景: 表中的数据本身就有独立性, 例如表中分别记录各个地区的数据或者不同时期的数据, 特别是有些数据常用, 有些数据不常用; 需要把数据存放在多个介质上

缺点: 给永盈增加复杂度, 通常查询时需要多个表名, 查询所有数据都需要union操作; 在许多数据库应用中, 这种复杂性会超过它带来的有点, 查询时会增加读一个索引层的磁盘次数

(2) 垂直分表: 把主键和一些列放在一个表, 然后把主键和另外的列放在另一个表

使用场景: 如果一个表中某些列常用, 而某些列不常用; 可以使数据行变小, 一个数据页能存储更多数据, 查询时减少i/o次数

缺点: 管理冗余列, 所有操作都需要join操作

(3) 分表缺点: 有些分表的策略基于应用层的逻辑算法, 一但逻辑算法改变, 整个 分表都会改变, 扩展性差; 对于应用层来说逻辑算法无疑是增加开发成本

 

3. Mysql的复制原理及负载均衡

工作原理: 在主库上把数据更改记录到二进制日志; 从库将主库的日志复制到自己的中继日志; 从库读取中继日志的时间, 将其重放到从库数据中

解决的问题:

(1) 数据分布: 随意停止或开始复制, 并在不用地理位置分布数据备份

(2) 负载均衡: 降低单个服务器的压力

(3) 高可用和故障切换: 帮助应用程序避免单点失败

(4) 升级测试: 可以使用高版本mysql作为从库测试查询方面有为有问题

 

解题方法: 充分掌握分区和分表的工作原理和适用场景, 在面试中此类题通常比较灵活, 会给一些现有公司遇到的问题的场景, 大家可以根据分区和分表以及mysql复制/负载均衡的适用场景来根据情况进行回答

 

真题: 设定网站的用户数量在千万级, 但是活跃用户的数量只有1%, 如何通过优化数据库提高活跃用户的访问速度?

 

14. Mysql的安全

真题: sql语句需要考虑哪些安全性?

1. sql查询的安全方案

(1) 使用预处理语句防止sql注入(因为预处理语句已经被解析过了从而还可以提高执行效率)

 

 

 

(2) 写入数据库的数据要进行特殊字符的转义(比如引号和双引号也是为了防止注入)

(3) 查询错误信息不要返回给用户, 将错误记录到日志中

注意: php端尽量使用pdo对数据库进行操作, pdo拥有对预处理语句很好的支持的方法, mysqli也有, 但是可扩展性不如pdo, 效率虽然高于pdo, mysql函数在新版本中已经趋于淘汰, 所以不建议使用,而且它没有很好的支持预处理的方法

 

2. Mysql 的其他安全设置

(1) 定期做数据备份

(2) 不给查询用户root权限, 合理分配权限

(3) 关闭远程访问数据库权限

(4) 修改root口令, 使用较复杂的root口令

(5) 删除多余的用户

(6) 改变root用户的名称

(7) 限制一般用户浏览其他库

(8) 限制用户对数据文件的访问权限

 

解题方法:通常情况下sql安全的考点都在防sql注入的问题, 因此只要遇到此类考点, 优先考虑sql注入的防护手段

 

真题: 为什么使用pdo和mysqli连接数据库比mysql函数库更加安全

Mysql函数库本身是不支持防注入的.

 

你可能感兴趣的:(MySQL,学习笔记)