Mysql优化方案(整理)

时间:2022-09-20 20:40:33

1.对于复杂查询,例如报表等多join的查询,尽量使用缓存,使用缓存的时候注意,now(),Rand(),currDate()等变化的函数是无法使用缓存,例如:SELECT username FROM user WHERE signup_date >= CURDATE(),可以使用变量代替函数(PHP),或者可以把参数通过程序计算出,然后传到sql中;

开启mysql缓存:在my.ini配置文件写入两行: query_cache_type 和 query_cache _size,size代表缓存大小, query_cache_type为 0 代表不使用缓冲, 1 代表使用缓冲,2 代表根据需要使用。

设置 1 代表缓冲永远有效,如果不需要缓冲,就需要使用如下语句:

 代码如下 复制代码

SELECT SQL_NO_CACHE * FROM my_table WHERE ...

如果设置为 2 ,需要开启缓冲,可以用如下语句:

 代码如下 复制代码

SELECT SQL_CACHE * FROM my_table WHERE ...

可以通过命令:SHOW VARIABLES LIKE '%query_cache%';查看缓存信息;

Mysql优化方案(整理)

通过命令:show status like 'Qca%';查看缓存命中、缓存容量等信息。
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_queries_in_cache | 8 |
| Qcache_inserts | 545875 |
| Qcache_hits | 83951 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2343256 |
| Qcache_free_memory | 33508248 |
| Qcache_free_blocks | 1 |
| Qcache_total_blocks | 18 |
+-------------------------+----------+
通过命令: show status like 'Com_sel%';查看查询语句数量;
+---------------+---------+
| Variable_name | Value |
+---------------+---------+
| Com_select | 2889628 |
+---------------+---------+
1 row in set (0.01 sec)

由上可看,MySQL 命中了 2,889,628 条查询中的 83,951 条,而且 INSERT 语句只有 545,875 条。因此,它们两者的和和280万的总查询相比有很大差距,因此,我们知道本例使用的缓冲类型是 2 。

2.对于复杂查询可以使用EXPLAIN解释优化sql,从数据量、索引等方面对sql进行优化处理。

3.对于确定返回一条数据的sql请使用limit 1;

4.关于索引,使用like ‘%username%’ 是无法应用索引的,可以将username建立fulltext索引以提高效率;两个表关联尽量使用索引关联,注意关联字段数据类型必须一致,否则是无法应用索引;

针对索引:列出一些常用技巧

  负向条件查询不能使用索引;

  前导模糊查询不能使用索引,fulltext类型索引除外,非前导模糊查询例如like ‘username%’则可以应用索引;

  列计算不能应用索引,例如sum(column);

  组合索引的顺序不影响索引触发,比如组合索引a b c,使用b a c ,b a,a,c a,都会命中索引,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边;

  频繁更新的列上不能建立索引,因为索引修改会比普通列产生更大的开销。

5.关于随机条数,不能使用select from table order by rand() limit 来实现,效率极低;不能把rand应用在order中!关于随机条数可以使用自定方案来获取,例如:

select username from table t1 join(select round(Rand()*(select max(id) from table)) as id) as t2 where t1.id>=t2.id limit 20;

6.绝对不能直接select *!可以使用select count(*) 来获取数据量,或者返回具体字段例如:select username from ...;

7.推荐使用PROCEDURE ANALYSE() 来优化你的表结构,尤其是你的表字段很多的时候。

procedure analyse();语法如下

select column from table_name procedure analyse();

8.针对大数据的insert 和delete操作,尽量拆分成多个数据操作进行,否者。后果。。。。啧啧啧。

9.针对mysql的INNODB引擎,支持事物方面,主要是采用redo log和undo log来实现事物的回滚和提交;

任何针对数据库的修改都会先写入一个叫buffer pool的缓存当中,由专门的刷新线程将修改数据阶段性刷新到磁盘从而持久化数据,但当刷新的过程中,数据库非正常中断,会造成数据丢失,为避免这样的数据丢失,mysql引入re-do log来记录数据修改,在非正常中断发生后能够恢复数据到一个正确的状态,但是会增加写入re-do log的开销。

摘一段例子:

假设有2个数值,分别为A和B,值为1,2

1. start transaction;

2. 记录 A=1 到undo log;

3. update A = 3;

4. 记录 A=3 到redo log;

5. 记录 B=2 到undo log;

6. update B = 4;

7. 记录B = 4 到redo log;

8. 将redo log刷新到磁盘

9. commit

在1-8的任意一步系统宕机,事务未提交,该事务就不会对磁盘上的数据做任何影响。如果在8-9之间宕机,恢复之后可以选择回滚,也可以选择继续完成事务提交,因为此时redo log已经持久化。若在9之后系统宕机,内存映射中变更的数据还来不及刷回磁盘,那么系统恢复之后,可以根据redo log把数据刷回磁盘。

所以,redo log其实保障的是事务的持久性和一致性,而undo log则保障了事务的原子性。

10.基础数据集应尽量少,避免全表数据查询。

未完待续。。。。。嘎嘎嘎。。。