400 028 6601

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

MySQL中如何优化索引

MySQL中如何优化索引,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

为诸暨等地区用户提供了全套网页设计制作服务,及诸暨网站建设行业解决方案。主营业务为成都做网站、网站建设、诸暨网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

文章的脑图如下:

MySQL中如何优化索引

索引优化规则

1、like语句的前导模糊查询不能使用索引

select * from doc where title like '%XX';   --不能使用索引 select * from doc where title like 'XX%';   --非前导模糊查询,可以使用索引

因为页面搜索严禁左模糊或者全模糊,如果需要可以使用搜索引擎来解决。

2、union、in、or 都能够命中索引,建议使用 in

union能够命中索引,并且MySQL 耗费的 CPU 最少。

select * from doc where status=1 union all select * from doc where status=2;

in能够命中索引,查询优化耗费的 CPU 比 union all 多,但可以忽略不计,一般情况下建议使用 in。

select * from doc where status in (1, 2);

or 新版的 MySQL 能够命中索引,查询优化耗费的 CPU 比 in多,不建议频繁用or。

select * from doc where status = 1 or status = 2

补充:有些地方说在where条件中使用or,索引会失效,造成全表扫描,这是个误区:

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

select * from doc where status != 1 and status != 2;

可以优化为 in 查询:

select * from doc where status in (0,3,4);

4、联合索引最左前缀原则

select uid, login_time from user where login_name=? andpasswd=?
  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 建立联合索引的时候,区分度最高的字段在最左边

  3. 存在非等号和等号混合判断条件时,在建立索引时,把等号条件的列前置。如 where a>? and b=?,那么即使a 的区分度更高,也必须把 b  放在索引的最前列。

  4. 最左前缀查询时,并不是指SQL语句的where顺序要和联合索引一致。

select uid, login_time from user where passwd=? andlogin_name=?

假如index(a,b,c), where a=3 and b like 'abc%' and c=4,a能用,b能用,c不能用。

5、不能使用索引中范围条件右边的列(范围列可以用到索引),范围列之后列的索引全失效

select * from employees.titles where emp_no < 10010' and title='Senior Engineer'and from_date between '1986-01-01' and '1986-12-31'

6、不要在索引列上面做任何操作(计算、函数),否则会导致索引失效而转向全表扫描

例如下面的 SQL 语句,即使 date 上建立了索引,也会全表扫描:

select * from doc where YEAR(create_time) <= '2016';

可优化为值计算,如下:

select * from doc where create_time <= '2016-01-01';

比如下面的 SQL 语句:

select * from order where date < = CURDATE();

可以优化为:

select * from order where date < = '2018-01-2412:00:00';

7、强制类型转换会全表扫描

字符串类型不加单引号会导致索引失效,因为mysql会自己做类型转换,相当于在索引列上进行了操作。

如果 phone 字段是 varchar 类型,则下面的 SQL 不能命中索引。

select * from user where phone=13800001234

可以优化为:

select * from user where phone='13800001234';

8、更新十分频繁、数据区分度不高的列不宜建立索引

9、利用覆盖索引来进行查询操作,避免回表,减少select * 的使用

Select uid, login_time from user where login_name=? and passwd=?

10、索引不会包含有NULL值的列

只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时,尽量使用not  null 约束以及默认值。

11、is null, is not null无法使用索引

12、如果有order by、group by的场景,请注意利用索引的有序性

order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort 的情况,影响查询性能。

如果索引中有范围查找,那么索引有序性无法利用,如 WHERE a>10 ORDER BY b;,索引(a,b)无法排序。

13、使用短索引(前缀索引)

14、利用延迟关联或者子查询优化超多分页场景

MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset  特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。

示例如下,先快速定位需要获取的id段,然后再关联:

selecta.* from 表1 a,(select id from 表1 where 条件 limit100000,20 ) b where a.id=b.id;

15、如果明确知道只有一条结果返回,limit 1 能够提高效率

select * from user where login_name=?;
select * from user where login_name=? limit 1

自己明确知道只有一条结果,但数据库并不知道,明确告诉它,让它主动停止游标移动。

16、超过三个表最好不要 join

17、单表索引建议控制在5个以内

18、SQL 性能优化 explain 中的 type:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好

19、业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引

不要以为唯一索引影响了 insert  速度,这个速度损耗可以忽略,但提高查找速度是明显的。另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

20.创建索引时避免以下错误观念

索引越多越好,认为需要一个查询就建一个索引。

宁缺勿滥,认为索引会消耗空间、严重拖慢更新和新增速度。

抵制惟一索引,认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。

过早优化,在不了解系统的情况下就开始优化。

索引选择性与前缀索引

Index Selectivity = Cardinality / #T
SELECT count(DISTINCT(title))/count(*) AS Selectivity FROM employees.titles; +-------------+ | Selectivity | +-------------+ |      0.0000 | +-------------+
EXPLAIN SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido'; +----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+ | id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows   | Extra       | +----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+ |  1 | SIMPLE      | employees | ALL  | NULL          | NULL | NULL    | NULL | 300024 | Using where | +----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+
SELECT count(DISTINCT(first_name))/count(*) AS Selectivity FROM employees.employees; +-------------+ | Selectivity | +-------------+ |      0.0042 | +-------------+ SELECT count(DISTINCT(concat(first_name, last_name)))/count(*) AS Selectivity FROM employees.employees; +-------------+ | Selectivity | +-------------+ |      0.9313 | +-------------+
SELECT count(DISTINCT(concat(first_name, left(last_name, 3))))/count(*) AS Selectivity FROM employees.employees; +-------------+ | Selectivity | +-------------+ |      0.7879 | +-------------+
ALTER TABLE employees.employees ADD INDEX `first_name_last_name4` (first_name, last_name(4));
SHOW PROFILES; +----------+------------+---------------------------------------------------------------------------------+ | Query_ID | Duration   | Query                                                                           | +----------+------------+---------------------------------------------------------------------------------+ |       87 | 0.11941700 | SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido' | |       90 | 0.00092400 | SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido' | +----------+------------+---------------------------------------------------------------------------------+

关于MySQL中如何优化索引问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。


标题名称:MySQL中如何优化索引
本文网址:http://mbwzsj.com/article/pisjhd.html

其他资讯

让你的专属顾问为你服务