Mysql优化

2019-05-16  本文已影响0人  蜡笔没了小新_e8c0

优化

首先,按照三范式的要求创建表,即满足数据不冗余。同时还可以对一些表进行分表操作,分表分为水平分表和垂直分表,水平分表可以按照时间,id,hash值进行分表,例如微博就可以采用时间分表,一些旧的微博内容就可以单独提取出来。垂直分表是将字段拆分出来,将一些长度比较大的字段拆分成一个新表,例如博客系统,文章内容单独拆成一个表,因为文章内容查看的次数相对较少,内容又比较大所以可以拆分出来。创建表时还应该选择合适的数据库引擎,比如mysql常用的InnoDB和myisam,InnoDB支持事务和外键,采用的也是行级锁,适合一些修改操作频繁的表,而myisam支持全文索引,采用的是表级锁,适合查询比较多的表。同时,还可以借助redis实现缓存功能。此外,也可以采用主从服务的方式,实现读写分离,主服务器进行写操作,从服务器进行读操作,从服务器负责监听主服务器,如果主服务器执行了写操作,会将相应的写操作发给从服务器进行数据的更新。

索引

如何定位并优化慢查询Sql

sql语句:

show variables like '%quer%';   //显示属性
show status like '%slow_queries%';    //显示慢语句条数
set global slow_query_log = on;    //开启慢语句查询日志
set global long_query_time = 1;    //设置时间

InnoDB和MyISAM之间的区别

InnoDB MyISAM
事务 支持 不支持
外键 支持 不支持
具体行数 不保存 保存
索引类型 聚集索引 稀疏索引

聚集索引和稀疏索引

聚集索引的好处?

InnoDB和MyISAM的锁不同

事务

sql操作:

select @@tx_isolation;   // 显示隔离级别

事务并发访问问题

当前读和快照读

事务的快照时间是按照第一个select出现来确认的,即如果在第一个select语句之前执行相应的修改操作,快照取出的值也是按照修改后的。

对主键索引或者唯一索引使用Gap锁情况

存储过程

DROP PROCEDURE IF EXISTS proc_initData;
DELIMITER $
CREATE PROCEDURE proc_initData()
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i<=100000000 DO
        INSERT INTO user(username,age) VALUES(CONCAT('用户',i),i/1000);
        SET i = i+1;
    END WHILE;
END $
CALL proc_initData();

慢查询

1.select * from table where a>0 and b<0,ab是联合索引,问索引能不能命中?

可以命中,不过key_len只有一半。

2.MySql的char和varchar的区别?

3.sql索引失效场景?

4.事务是什么?事务的四大特性?

事务是用户定义的一个操作序列。

1.整形宽度

对于MySQL而言,可以为整数类型指定宽度,但是对于MySQL而言,无论设置什么宽度对于存储和计算而言都是一样的,只是规定了交互工具用来显示字符的个数。

2.varchar和char

3.datatime和timestamp

4.IP地址存储

使用无符号整数存储IP地址。

5.存储计数内容?

可以一个计数器表,里面就一个字段count用来保存计数值,然后为了提高并发更新性能,可以将先创建若干条计数记录,进行更新时只需随机选择一行进行更新,当获取总计数值时对相关记录进行求和操作。

如果需要按照日期进行计数可以按照如下方式建立表:

create table daily_hit_counter(
    day date not null,
    slot tinyint unsigned not null,
    cnt int unsigned not null,
    primary key(day,slot)
)ENGINE = INNODB;

利用ON DUPLICATE KEY UPDATE 的方式进行值的加1。


insert into daily_hit_counter(day,slot,cnt) values(CURRENT_DATE,RAND()*100,1) on DUPLICATE key UPDATE cnt = cnt +1;

同时可以开启定时任务对计数值进行合并。

update daily_hit_counter as c inner join (
    select day,SUM(cnt) as cnt,MIN(slot) as mslot
    from daily_hit_counter group by day
) as x using(day) 
set c.cnt = IF(c.slot = x.mslot,x.cnt,0),
 c.slot = IF(c.slot = x.mslot,0,c.slot);
 delete from daily_hit_counter where slot <> 0 and cnt = 0;

6.ALTER COLUMN 和 MODIFY COLUMN区别

7.如何选择组合索引列的排序?

在不考虑排序和分组的情况下可以按照选择性最高的列放在最前面的原则。有的列如果需要经常进行范围查询(age),就需要把这类字段放在最后;或者可以使用IN查询罗列条件(sex),就可以把这样的列放在前面。

8.InnoDB使用随机主键的缺点?

9.覆盖索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就之为“覆盖索引”。

10.MySQL中的状态

11.IN()查询

在大部分数据库系统中,IN()完全等同于多个OR条件的子句。而在MySQL中,会先将IN()列表中的数据先进行排序,然后通过二分查找的方式来确定列表中的值是否满足条件,这是一个O(logn)复杂度的操作,而OR查询的复杂度为O(n)。对于IN()列表中有大量取值的时候,MySQL的处理速度将会更快。

12.查询优化器

优化器的作用是找到查询语句多种执行方式中最好的那种,是基于成本优化。

12.1 查询优化器不能选择最优的执行计划

12.2 优化的类型

13.explain中的rows是什么?

rows是对SQL执行过程中会被扫描的行数的一个估计值。

14.mysql获取锁的过程示例

SELECT * FROM users WHERE id = 6 FOR UPDATE;

1.事务A先拥有users表的意向排他锁;
2.拥有id为6的行排他锁。

LOCK TABLES users READ;

1.首先检测到事务A拥有users表的排他锁;
2.事务B阻塞。

SELECT * FROM users WHERE id = 5 FOR UPDATE;

1.事务C申请users表的意向排他锁;
2.检测到事务A执行意向排他锁,由于意向锁之间兼容,所以拿到users表的意向排他锁;
3.检测id为5的行是否存在锁,因为没有加锁,所以事务C获取到id为5的行的排他锁。

上一篇下一篇

猜你喜欢

热点阅读