前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL性能优化点记录

MySQL性能优化点记录

作者头像
用户7657330
发布2020-08-14 15:13:03
1K0
发布2020-08-14 15:13:03
举报
文章被收录于专栏:程序生涯

第一章

myisam,可以基于blob和text的前500字节,创建索引

myisam 支持fulltext

延迟更新索引

(delay_key_write)

CREATE TABLE `table3` (

`id` INT(11) NOT NULL AUTO_INCREMENT,

`name` VARCHAR(30) DEFAULT NULL,

`id2` INT(11) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=MYISAM DEFAULT CHARSET=utf8 DELAY_KEY_WRITE = 1

ALTER TABLE table2 DELAY_KEY_WRITE = 1

只有myisam支持全文检索

第三章 索引方面

字段尽可能的小

尽量避免null,用0代替。但是对性能的提升很小,最后考虑,索引的列最好不适用null

mysql性能优化点记录

一、优化数据访问

查询性能低下的最基本原因就是访问了太多数据。一些查询不可避免的要筛选大量的数据,单这并不常见。大部分性能欠佳的查询都可以用减

少数据访问的方式进行修改。在分析性能欠佳的查询的时候,下面两个步骤比较有用:

1.应用程序是否在获取超过需要的数据。这通常是访问了过多的行或列。

2.mysql服务器是否分析了超过需要的行。

对于访问的数据行很大,而生成的结果中数据行很少,可以尝试修改。

1.使用覆盖索引,它存储了数据,所以存储引擎不会去完整的行。

2.更改架构,一个例子就是使用汇总表。

3.重写复杂的查询,让mysql的优化器可以优化的执行。

二、复杂查询和多个查询

1.把一个复杂的查询分解为多个简单的查询。(mysql一般的服务器,每秒钟可以处理50 000个查询)

2.

三、缩短查询

将一次处理大量数据的操作,分解为多个小操作。循环的方式每次处理一部分数据。一次删除不要超过10 000行(delete)

四、分解链接

把一个多表连接分解成多个单个查询,然后在应用程序里实现联接。

这样的优势

1.缓存效率高。

2.mysql,可以更有效的利用表锁,查询会锁住单个表较短时间。

3.应用程序进行联接可以更方便的拓展数据库,把不同表放在不同服务器上。

4.查询更高效。

5.可以减少多余的行访问,可以减少网络流量和内存消耗。

小结:在程序端进行联接的效率更高

1.可以缓存早期查询的大量数据。

2.使用了多个myisam表

3.数据分布在不同的服务器上。

4.对于大表使用in替换联接

5.一个连接引用了同一个表多次。

当你重建汇总和缓存表的时候,在操作的时候你常常需要它们的数据保持可见。你可以使用“shadow table”(影像表)来实现。当你已经创建它之后,你可以使用原子性的重命名来交换这些表。举个例子,如果

你需要重建my_summary,你能创建my_summary_new,填充数据,把它和真正的表作交换。

mysql> DROP TABLE IF EXISTS my_summary_new, my_summary_old;

mysql> CREATE TABLE my_summary_new LIKE my_summary;

-- populate my_summary_new as desired

mysql> RENAME TABLE my_summary TO my_summary_old, my_summary_new TO my_summary;

mysql执行查询的一般性过程

1.客户端发送查询到服务器

2.服务器检查查询缓存,

3.服务器解析,预处理和优化查询,生成执行计划。

4.执行引擎调用存储引擎api执行查询。

5.服务器将结果发送到客户端。

mysql客户端、服务器协议

1.协议是半双工的。mysql服务器在某个时间可以发送或者接受数据,单不能同时发送和接收。所有没有办法阶段消息。

2.客户端用一个数据包将查询发送到服务器,所以max_packet_size这个配置参数对于大查询很重要的原因。

3.客户端从服务器提取数据的时候是服务器产生数据的同时把它们“推”到客户端的,客户端只需要接收推出来的数据,无法告诉服务器停止

发送数据。

查询缓存

SELECT SQL_NO_CACHE * FROM ol_answerlog LIMIT 1000

SHOW STATUS LIKE 'last_query_cost'

关键字straight_join 强制执行引擎按照查询中表现的顺序来进行链接操作。

严格的说,mysql不回尝试减少读取的行数,它只会试着优化对页面的读取,但是行数可以大致显示查询的开销。

连接优化器试着产生最低开销的查询计划。在可能的时候,他会从单表计划开始,检查所有的可能的子树的组合。但是对n个表连接,需要检

查组合的数量就是n的阶乘,这个数量称为ie搜索空间, 它增长非常快,如果一个查询需要连接10个表,那么要检查的数量将是10!=36288000

当搜索空间非常巨大的时候优化耗费的时间就会非常长,这时候服务器就不回执行完整的分析,但表的数量超过optimizer_search_depth的值

时,它就会走捷径,比如执行所谓的 贪婪搜索。

SHOW TABLE STATUS FROM `servant_591up`WHERE ENGINE IS NOT NULL

AND NAME LIKE '%ol_ans%';

max min的优化

select min(id) from ol_user where username = 'dddd@dd.com'

(一)max 和 min 会扫描整张表。

mysql的主键都是按照升序排列的。

可以使用limit 改写查询,

select userid from ol_user where username='test@nd.com' limit 1

(二)对同一表进行select 和 update

mysql不允许对一个表进行update的时候进行select

update tb1 as out_table

set cnt = (select count(*) from tb1 as inner_table where inner_table.type = outer_table.type);

一个实现方式:衍生表,当成临时表来处理。

update tb1 inner join(

select type,count(*) as cnt

from tb1

group by type

)as der using(type)

set tb1.cnt = der.cnt;

(三、)优化特定类型的查询

1.count

count的作用 统计值的数量和统计行的数量

值是非空表达式(NOT NULL)

一个常见的错误就是在想统计行数的时候,在count的括号中放入列名,如果想知道结果的行数,应该总是使用COUNT(*),这可以清晰的说明意

图,并且得到好的性能。

2.MYISAM

只有在没有WHERE条件的时候COUNT(*)才是最快的,在有条件过滤的时候并不非常快。

3.简单优化

可以利用MYISAM对COUNT(*)的优化对已经有索引的一小部分做统计。

SELECT COUNT(*) FROM WORD.CITY WHERE ID>5;

优化为下面的语句

SELECT (SELECT COUNT(*) FROM CITY) - COUNT(*) FROM CITY WHEREID<=5;

这样的explain只扫描6行数据

使用一个查询统计同一列中不同值的数量。

select sum(if(color='blue',1,0)) as blue,sum(if(color='red',1,0)) as red from items;

下面是一个等价查询

select count(color='blue' or null) as blue,count(color='red' or null) as red from items;

(四)优化联接

1.确保on 或using使用的列上有索引。

通常只需要在联接中的第2个表上添加索引就可以。

2.确保group by或order by只引用一个表中的列。这样可以使用索引。

3.谨慎升级mysql

(五)优化子查询

对于子查询,尽可能的使用联接。

(五)优化group by和distinct

1.主要方式:索引

2.优化group by的策略:临时表或文件排序分组。

SQL_SMALL_RESULT : 强制使用临时表

SQL_BIG_RESULT :强制使用文件排序

通常对表的id进行分组会更加高效

可以使用SQL_MODE参数禁止SELECT中使用在group by中出现的列

子查询创建的临时表不支持索引。

所以要让子查询创建的临时表尽可能的小。

3.使用ROLL UP 优化GROUP BY

WITH ROLLUP

最好的方式是将WITH ROLLUP 放在应用程序里。

注意: Rollup 与 order by 相互排拆

(六)优化limit和offset

LIMIT 和ORDER BY 一块使用。

如果没有索引,就使用文件排序。

(七)优化SQL_CALC_FOUND_ROWS

这个地方很重要

一个技巧:在含有limit的查询中添加SQL_CALC_FOUND_ROWS,这样就可以知道没有limit的时候会返回多少行数据。服务器会预测将会发现多少

行数据。但是服务器并不能真正的做到,只是告诉服务器生成结果并丢掉结果中不需要的部分。而不是在得到需要的数据后就立即停止。这个

选项代价很高。

一个非常好的设计:

如果每页有20条结果,那么应该查询limit 21行数据,只显示20条,如果结果中有21行,那么就会有下一页。

另一种方式:就是提取并缓存大量数据,比如1000行,然后从缓存中获取后续页面的数据。

可以让程序知道一共有多少数据,少于1000,程序知道有多少页,如果大于1000,可以显示找到的结果超过1000个。

这两种都比重复产生完整的结果效率高。

如果以上两种都不可以使用,可以使用覆盖索引,使用单独的count(*)会更好

(八)优化联合 union

mysql总是使用临时表来执行union,无法做更多的优化

重要的是,一定要使用union all,除非真的是需要服务器消除重复的行,

否则mysql会使用distinct选项,来确保所有行数据的唯一性。

(九)查询优化提示

可以用一些提示控制优化器的行为,每个提示只影响当前查询。

1.HIGH_PRIORITY 和 LOW_PRIORITY

HIGH_PRIORITY 让mysql 将一个select语句放在其他的语句的前面,mysql将它放在队列的前面,而不是在队列中等待。可以用在insert语句中

low——priority正好相反,可以用在SELECT INSERT UPDATE REPLACE DELETE

这两个选项在表锁的存储过程中有效,在innerdb无效,在myisam要小心使用,严重影响性能,禁止并发插入。

2.delayed

用户insert delete

立即返回,放入缓冲当中,,无法使用LAST_ISNERT_ID()

3.STRAIGHT_JOIN

强制mysql按照查询中表出现的顺序来连接表。

出现在两个连接的表中间时,强制这两个表按照顺序连接。

用途:mysql没有选择更好的链接,或者优化器需要花费很长时间来确定连接顺序。

4.SQL_SMALL_RESULT SQL_BIGA_RESULT

用在group by 和distinct语句中的,如何使用临时表

SQL_SMALL_RESULT :结果很小,可以放在索引过的临时表中,

SQL_BIGA_RESULT:结果很大,最好使用磁盘上的临时表进行排序。

5.SQL_BUFFER_RESULT

将结果放在临时表中,并且要尽快释放掉表锁。

6.SQL_CACHE SQL_NO_CACHE

7.SQL_CALC_FOUND_ROWS

在limit自居计算完整的结果集,可以通过found_ROWS()来取得它的行数,

最好不使用这个提示、

8.FOR_ UPDATE 和 LOCK IN SHARE MODE

只有innodb支持,提示控制锁定,仅对行锁起作用。select语句中

9.USE INDEX 和 IGNORE INDEX 和 FORCE INDEX

控制索引的使用,在mysql5.1中,还有 FOR ORDER BY FOR GROUP BY

用途:告诉优化器表扫描比索引代价高很多,

重要的系统变量

Optimizer_search_depth

优化器检查执行计划的深度。

Optimizer_prune_level

根据检查的行数来决定跳过一些查询计划。

(九) 用户自定义变量

一些需要注意的问题:

会禁止缓存

不能用于文字常量和标识的地方(表名,列名,limit)

和连接有关,不能跨通信使用

如果使用连接池,会引起代码隔离

mysql 5.0大小写敏感

不能显示的声明类型,最好的方式给变量显示的一个初始值 0 0.0 ‘’,

用户自定义变量的类型是动态的,赋值的时候才会变化。

优化器有时候会把变量优化掉。

set @ont:=1; :=运算符的优先级,低于其他的,最好使用括号()。。 也可以使用=赋值,最好统一使用:=

未定义的变量不会引起语法错误,很容易犯错。

五、mysql高级特性

查询缓存命中率

Qcache_hits/(Qcache_his+Com_select) show status

1.缓存未命中原因

查询不可缓存,不确定函数。CURRENT_DATE,结果太大, Qcache_not_cached 会记录两种无法缓存的查询数量。

服务器以前从来没见过这个缓存。

查询结果被缓存过,但是服务器把它移除。

很多缓存失效。

2.很多缓存未命中,但是不能缓存的查询很少。

查询缓存未被激活。

服务器看到了以前未见过的查询

缓存失效。

A:如何对查询缓存进行维护调优

Query_cache_type

表示缓存是否被激活,on off demand,demand:只有sql_cache的查询才可以被缓存。

Query_cache_size

缓存的总内存,字节单位。1024的倍数,

Query_cache_min_res_unit

分配缓存块的最小值

Query_cache_limit

限制了mysql存储的最大结果。如果超过这个值,会丢掉已经缓存过的值,并增加Query_not_chched的值。如果是这样需要在查询上增

加QUERY_NO_CACHE

Query_cache_wlock_invalidate

是否缓存其他链接已经锁定了的表,默认off,

B:优化的一些法则

减少碎片

需要仔细选择Query_cache_min_res_unit,可以避免在查询缓存中造成大量的内存浪费。

最佳设置根据典型查询结果确定。可以使用内存(Queryc_cache_size - Query_free_memory)除以Query_queries_in_cache

得到查 询的平均大小。可以通过query_cache_limit的值来阻止缓存大结果。

可以检查Qcache_free_blocks来探测缓存中碎片的情况,显示缓存中有多少内存块出于free状态。如果Qcache_free_blocks

大致 等于Qcache_total_blocks/2,则说明碎片非常严重,如果Qcache_lowmen_prunes的值在增加并且有大量的

自由块,说明碎片导致查 询整 被从缓存中永久删除。

可以使用FLUSH QUERY CACHE命令移除碎片。会把所有的存储块向上移动,把自由块移动到底部。会阻止访问查询缓存,锁定

整个服务器,通常这个速度很快,不会移除缓存中的数据,

RESET QUERY CACHE会清除缓存数据。

提高缓存可用性。

如果没有碎片,但是命中率不高,应该给缓存分配较少的内存。

服务器清理查询的时候会Qcache_lowmen_prunes的值会增加,如果值增加的过快则说明:

1.如果自由块很多,碎片

2.如果自由块比较少,说明工作负载使用的内存超过所分配的内存。可以检查Qcache_free_memory知道未使用的内

存。

可以禁用缓存查看缓存是否真的有效果

query_cacha_size = 0,可以关闭缓存(query_cache_type 无法影响已经打开了的链接,也不会把内存归还给服务

器。)

5.1.5 innodb和查询缓存

6.2.2 myisam键缓存

SHOW VARIABLES LIKE 'key_buffer_size'

键缓冲区,myisam本身只缓存索引,没有数据。

应该让key_buffer_size占到保留内存的25-50%。但是对于mysql5.0,最大上限都是4G

但是可以创建多个命名键缓冲区。可以一次在内存中保存4G以上的数据。

key_buffer_1 key_buffer_2 都是1G

在配置文件增加两行

key_buffer_1.key_buffer_size = 1G

key_buffer_2.key_buffer_size = 1G

可以使用cache index 命令把表映射到缓存

也可以用下面的命令把表的索引保存到key_buffer_1

cache index t1,t2 in key_buffer_1

也可以使用load index把表的索引预加载到缓存中

load index into cache t1,t2;

缓存命中率

100-((Key_reads * 100) / Key_read_requests)

缓存使用百分比

100-((Key_blocks_unused * key_cache_block_size) * 100 / key_buffers_size)

innodb 可以使用裸设备

raw

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/03/17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一章
  • 第三章 索引方面
  • mysql性能优化点记录
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档