MySql中sql怎么优化


这篇文章主要介绍了MySql中sql怎么优化,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。system > const > eq_ref > ref > range > index > all。system:表仅有一行,基本用不到;const:表最多一行数据配合,主键查询时触发较多;eq_ref:对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型;ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取;range:只检索给定范围的行,使用一个索引来选择行。当使用=、、>、>=、、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range;index:该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小;all:全表扫描;实际sql优化中,最后达到ref或range级别。Using index:只从索引树中获取信息,而不需要回表查询;Using where:WHERE子句用于限制哪一个行匹配下一个表或发送到客户。除非你专门从表中索取或检查所有行,如果Extra值不为Using where并且表联接类型为ALL或index,查询可能会有一些错误。需要回表查询。Using temporary:mysql常建一个临时表来容纳结果,典型情况如查询包含可以按不同情况列出列的GROUP BY和ORDER BY子句时;索引原理及explain用法请参照前一篇:MySQL索引原理,explain详解备注:因为mysql优化器的缘故,与索引顺序不一致,也会触发索引,但实际项目中尽量顺序一致。where和order by一起使用时,不要跨索引列使用。优化一点,但效果不是很好,因为type是index类型,extra中依然存在using where。因为sql的编写过程解析过程因此我怀疑是联合索引建的顺序问题,导致触发索引的效果不好。are you sure?试一下就知道了。删除旧的不用的索引:索引改名更改索引顺序之后,发现type级别发生了变化,由index变为了range。range:只检索给定范围的行,使用一个索引来选择行。备注:in会导致索引失效,所以触发using where,进而导致回表查询。ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取;index 提升为ref了,优化到此结束。保持索引的定义和使用顺序一致性;索引需要逐步优化,不要总想着一口吃成胖子;将含in的范围查询,放到where条件的最后,防止索引失效;上一篇介绍过,联合查询时,小表驱动大表。小表也称为驱动表。其实就相当于双重for循环,小表就是外循环,第二张表(大表)就是内循环。虽然最终的循环结果都是一样的,都是循环一样的次数,但是对于双重循环来说,一般建议将数据量小的循环放外层,数据量大的放内层,这是编程语言的优化原则。再次代码测试:student数据:四条teacher数据:三条按照理论分析,teacher应该为驱动表。sql语句应该改为:优化一般是需要索引的,那么此时,索引应该怎么加呢?往哪个表上加索引?索引的基本理念是:索引要建在经常使用的字段上。由on teacher.id = student.id可知,teacher表的id字段使用较为频繁。left join on,一般给左表加索引;因为是驱动表嘛。备注:如果extra中出现using join buffer,表明mysql底层觉得sql写的太差了,mysql加了个缓存,进行优化了。小表驱动大表索引建立在经常查询的字段上sql优化,是一种概率层面的优化,是否实际使用了我们的优化,需要通过explain推测。1、复合索引,不要跨列或无序使用(最佳左前缀);2、符合索引,尽量使用全索引匹配;3、不要在索引上进行任何操作,例如对索引进行(计算、函数、类型转换),索引失效;4、复合索引不能使用不等于(!=或)或 is null(is not null),否则索引失效;5、尽量使用覆盖索引(using index);6、like尽量以常量开头,不要以%开头,否则索引失效;如果必须使用%name%进行查询,可以使用覆盖索引挽救,不用回表查询时可以触发索引;7、尽量不要使用类型转换,否则索引失效;8、尽量不要使用or,否则索引失效;如果主查询的数据集大,则使用in;如果子查询的数据集大,则使用exist;using filesort有两种算法:双路排序、双路排序(根据IO的次数)MySQL4.1之前,默认使用双路排序;双路:扫描两次磁盘(①从磁盘读取排序字段,对排序字段进行排序;②获取其它字段)。MySQL4.1之后,默认使用单路排序;单路:只读取一次(全部字段),在buffer中进行排序。但单路排序会有一定的隐患(不一定真的是只有一次IO,有可能多次IO)。注意:单路排序会比双路排序占用更多的buffer。单路排序时,如果数据量较大,可以调大buffer的容量大小。如果max_length_for_sort_data值太低,MySQL底层会自动将单路切换到双路。太低指的是列的总大小超过了max_length开发云主机域名_for_sort_data定义的字节数。提高order by查询的策略:选择使用单路或双路,调整buffer的容量大小;避免select * from student;(① MySQL底层需要对*进行翻译,消耗性能;② *永远不会触发索引覆盖 using index);符合索引不要跨列使用,避免using filesort;保证全部的排序字段,排序的一致性(都是升序或降序);慢查询日志就是MySQL提供的一种日志记录,用于记录MySQL响应时间超过阈值的SQL语句(long_query_time,默认10秒) ;慢日志默认是关闭的,开发调优时打开,最终部署时关闭。(1)检查是否开启了慢查询日志:(2)临时开启:(3)重启MySQL:(4)永久开启:/etc/my.cnf中追加配置:放到[mysqld]下:(1)查看默认阈值:(2)临时修改默认阈值:(3)永久修改默认阈值:/etc/my.cnf中追加配置:放到[mysqld]下:long_query_time = 5;(4)MySQL中的sleep:(5)查看执行时间超过阈值的sql:慢查询的sql被记录在日志中,可以通过日志查看具体的慢sql。通mysqldumpslow工具查看慢sql,可以通过一些过滤条件,快速查出需要定位的慢sql。参数简要介绍:s:排序方式r:逆序l:锁定时间g:正则匹配模式(1)返回记录最多的3个SQL(2)获取访问次数最多的3个SQL(3)按时间排序,前10条包含left join查询语句的SQL打开此功能:set profiling = on;show profiles会记录所有profileing打来之后,全部SQL查询语句所花费的时间。缺点是不够精确,确定不了是执行哪部分所消耗的时间,比如CPU、IO。show profile all for query 上一步查询到的query_id。show variables like ‘%general_log%’开启全局日志:set global general_log = 1;set global log_output = table;读写:对同一个数据,多个读操作可以同时进行,互不干扰。写锁:如果当前写操作没有完毕,则无法进行其它的读写操作。表锁:一次性对一张表整体加锁。如MyISAM存储引擎使用表锁,开销小、加锁快、无死锁;但锁的范围大,容易发生冲突、并发度低。行锁:一次性对一条数据加锁。如InnoDB存储引擎使用的就是行锁,开销大、加锁慢、容易出现死锁;锁的范围较小,不易发生锁冲突,并发度高(很小概率发生高并发问题:脏读、幻读、不可重复读)lock table 表1 read/write,表2 read/write,…查看加锁的表:show open tables;如果某一个会话对A表加了read锁,则该会话可以对A表进行读操作、不能进行写操作。即如果给A表加了读锁,则当前会话只能对A表进行读操作,其它表都不能操作会话0给A表加了锁,其它会话的操作①可以对其它表进行读写操作②对A表:读可以,写需要等待释放锁。当前会话可以对加了写锁的表,可以进行任何增删改查操作;但是不能操作其它表;其它会话:对会话0中对加写锁的表,可以进行增删改查的前提是:等待会话0释放写锁。MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行增删改前,会自动给涉及的表加写锁。所以对MyISAM表进行操作,会有如下情况发生:(1)对MyISAM表的读操作(加读锁),不会阻塞其它会话(进程)对同一表的读请求。但会阻塞对同一表的写操作。只有当读锁释放后,才会执行其它进程的写操作。(2)对MyISAM表的写操作(加写锁),会阻塞其它会话(进程)对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。查看哪些表加了锁:show open tables;1代表被加了锁分析表锁定的严重程度:show status like ‘table%’;Table_locks_immediate:可能获取到的锁数Table_locks_waited:需要等待的表锁数(该值越大,说明存在越大的锁竞争)一般建议:Table_locks_immediate/Table_locks_waited > 5000,建议采用InnoDB引擎,否则采用MyISAM引擎。为了研究行锁,暂时将自动commit关闭,set autocommit = 0;show status like ‘%innodb_row_lock%’;Innodb_row_lock_current_waits:当前正在等待锁的数量
Innodb_row_lock_time:等待总时长。从系统启动到现在一共等待的时间
Innodb_row_lock_time_avg:平均等待时长。从系统启动到现在一共等待的时间
Innodb_row_lock_time_max:最大等待时长。从系统启动到现在一共等待的时间
Innodb_row_lock_waits:等待次数。从系统启动到现在一共等待的时间(1)查询student(2)更新student(3)加行锁通过select id,name,age from student for update;给查询加行锁。依旧修改成功,原因是MySQL默认是自动提交的,因此需要暂时将自动commit关闭set autocommit = 0;(1)如果没有索引,行锁自动转为表锁。(2)行锁只能通过事务解锁。(3)InnoDB默认采用行锁优点:并发能力强,性能高,效率高缺点:比表锁性能损耗大高并发用InnoDb,否则用MyISAM。感谢你能够认真阅读完这篇文章,希望小编分享的“MySql中sql怎么优化”这篇文章对大家有帮助,同时也希望大家多多支持开发云,关注开发云行业资讯频道,更多相关知识等着你来学习!

相关推荐: 怎么解决mysql MGR无法连接主节点的问题

这篇文章主要讲解了“怎么解决mysql MGR无法连接主节点的问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决mysql MGR无法连接主节点的问题”吧!万事不决看官方文档,官方文档有很明确说明:Re…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 06/29 15:12
下一篇 06/29 15:12

相关推荐