实践中如何优化 MySQL?
最好是按照以下顺序优化:
SQL 语句及索引的优化
数据库表结构的优化
系统配置的优化
硬件的优化
对数据库的优化
设计良好的数据库结构,允许部分数据冗余,尽量避免 join 查询,提高效率。
选择合适的表字段数据类型和存储引擎,适当的添加索引。
MySQL 库主从读写分离。
找规律分表,减少单表中的数据量提高查询速度。
添加缓存机制,比如 memcached,apc 等。
不经常改动的页面,生成静态页面。
书写高效率的SQL。比如SELECT * FROM TABEL改为SELECT field_1,field_2, field_3 FROM TABLE.
对 SQL 语句优化有哪些方法?
避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
避免在 where 子句中对字段进行函数或者表达式操作,这将导致引擎放弃使用索引而进行全表扫描
避免在where子句中使用!=或<>操作符,Mysql只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE使用索引
避免在where中使用OR来连接条件,否则可能导致引擎放弃索引来执行全表扫描,可以使用UNION进行合并查询
最好不要使用select * from t,用具体的字段列表代替"*",不要返回用不到的任何字段
limit offset rows关于分页查询,尽量保证不要出现大的offset
比如limit 10000,10相当于对已查询出来的行数弃掉前10000行后再取10行,完全可以加一些条件过滤一下(完成筛选),而不应该使用limit跳过已查询到的数据。这是一个offset做无用功的问题。对应实际工程中,要避免出现大页码的情况,尽量引导用户做条件过滤
用EXISTS替代IN,用NOT EXISTS替 NOT IN。
避免在索引列上使用计算、IS NULL和IS NOT NULL 所以在设计表时尽量使用NOT NULL约束,有些数据会默认为NULL,可以设置默认值为0或者-1
Mysql中用exists代替in 需要看情况
exists对外表用loop逐条查询,每次查询都会查看exists的条件语句,当 exists里的条件语句能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真,返回当前loop到的这条记录,反之如果exists里的条 件语句不能返回记录行,则当前loop到的这条记录被丢弃,exists的条件就像一个bool条件,当能返回结果集则为true,不能返回结果集则为 false
下面两条语句比较性能
1: select * from A where exists (select * from B where B.id = A.id);
2: select * from A where A.id in (select id from B);
下面再看not exists 和 not in
- select * from A where not exists (select * from B where B.id = A.id);
- select * from A where A.id not in (select id from B);
看查询1,还是和上面一样,用了B的索引
而对于查询2,可以转化成如下语句
select * from A where A.id != 1 and A.id != 2 and A.id != 3;
可以知道not in是个范围查询,这种!=的范围查询无法使用任何索引,等于说A表的每条记录,都要在B表里遍历一次,查看B表里是否存在这条记录
故not exists比not in效率高
如果查询的两个表大小相当,那么用in和exists差别不大。
如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
例如:表A(小表),表B(大表)
1:
select * from A where cc in (select cc from B) 效率低,用到了A表上cc列的索引;
select * from A where exists(select cc from B where cc=A.cc) 效率高,用到了B表上cc列的索引。
相反的
2:
select * from B where cc in (select cc from A) 效率高,用到了B表上cc列的索引;
select * from B where exists(select cc from A where cc=B.cc) 效率低,用到了A表上cc列的索引。
not in 和not exists如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。
https://www.cnblogs.com/xianlei/p/8862313.html