MySQL之索引优化

打印 上一主题 下一主题

主题 537|帖子 537|积分 1611

1、在进行查询时,索引列不能是表达式的一部分,也不能是函数的参数,否则无法利用索引



  • 比方下面的查询不能利用 actor_id 列的索引:
  • #这是错误的
  • SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;
  • 优化方式:可以将表达式、函数操纵移动到等号右侧。如下:
  • SELECT actor_id FROM sakila.actor WHERE actor_id = 5 - 1;
  • 2、在需要利用多个列作为条件进行查询时,利用多列索引比利用多个单列索引性能更好

    • 比方下面的语句中,最好把actor_id 和 film_id 设置为多列索引。猿辅导有道题,详见链接,可以让明白更深刻。
    • SELECT film_id, actor_ id FROM sakila.film_actor
    • WHERE actor_id = 1 AND film_id = 1;
    • 3、让选择性最强的索引列放在前面。 见MySql最左前缀原则 索引的选择性是指:不重复的索引值和记录总数的比值。最大值为 1,此时每个记录都有唯一的索引与其对应。选择性越高,每个记录的区分度越高,查询效率也越高

      • 比方下面显示的效果中 customer_id 的选择性比 staff_id 更高,因此最好把 customer_id 列放在多列索引的前面。
      • 复制代码
      • SELECT COUNT(DISTINCT staff_id)/COUNT(*) AS staff_id_selectivity,
      • COUNT(DISTINCT customer_id)/COUNT(*) AS customer_id_selectivity,
      • COUNT(*)
      • FROM payment;
      • #效果如下
      • staff_id_selectivity: 0.0001
      • customer_id_selectivity: 0.0373
      • COUNT(*): 16049
      • 4、对于 BLOB、TEXT 和 VARCHAR 范例的列,必须利用前缀索引,只索引开始的部分字符。 前缀长度的选取需要根据索引选择性来确定
      • 5、索引包含全部需要查询的字段的值。具有以下优点: 索引通常远小于数据行的大小,只读取索引能大大镌汰数据访问量。 一些存储引擎(比方 MyISAM)在内存中只缓存索引,而数据依靠于操纵体系来缓存。因此,只访问索引可以不利用体系调用(通常比力费时)。 对于 InnoDB 引擎,若辅助索引可以或许覆盖查询,则无需访问主索引
      • 6、mysql在利用like进行暗昧查询的时间把%放后面,制止开头暗昧查询 由于mysql在利用like查询的时间只有利用后面的%时,才会利用到索引

        • 如:'%ptd_' 和 '%ptd_%' 都没有用到索引;而 'ptd_%' 利用了索引。
        • 复制代码
        • #进行全表查询,没有用到索引
        • EXPLAIN SELECT * FROM `user` WHERE username LIKE '%ptd_%';
        • EXPLAIN SELECT * FROM `user` WHERE username LIKE '%ptd_';
        • #有用到索引
        • EXPLAIN SELECT * FROM `user` WHERE username LIKE 'ptd_%';
        • 复制代码
        • 再好比:常常用到的查询数据库中姓张的全部人:
        • SELECT * FROM `user` WHERE username LIKE '张%';
        • 7、在表中创建索引,优先思量where、group by利用到的字段
        • 8、 尽量制止利用in 和not in,会导致数据库引擎放弃索引进行全表扫描

          • 好比:
          • SELECT * FROM t WHERE id IN (2,3)
          • SELECT * FROM t1 WHERE username IN (SELECT username FROM t2)
          • 优化方式:如果是一连数值,可以用between取代。如下:
          • SELECT * FROM t WHERE id BETWEEN 2 AND 3
          • 如果是子查询,可以用exists取代。如下:
          • SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)
          • 9、尽量制止利用or,会导致数据库引擎放弃索引进行全表扫描

            • 如:
            • SELECT * FROM t WHERE id = 1 OR id = 3
            • 优化方式:可以用union取代or。如下:
            • SELECT * FROM t WHERE id = 1
            • UNION
            • SELECT * FROM t WHERE id = 3
            • 10、 尽量制止进行null值的判断,会导致数据库引擎放弃索引进行全表扫描

              • SELECT * FROM t WHERE score IS NULL
              • 优化方式:可以给字段添加默认值0,对0值进行判断。如下:
              • SELECT * FROM t WHERE score = 0
              • 11、尽量制止在where条件中等号的左侧进行表达式、函数操纵,会导致数据库引擎放弃索引进行全表扫描

                • 比方:
                • SELECT * FROM t2 WHERE score/10 = 9
                • SELECT * FROM t2 WHERE SUBSTR(username,1,2) = 'li'
                • 优化方式:可以将表达式、函数操纵移动到等号右侧。如下:
                • SELECT * FROM t2 WHERE score = 10*9
                • SELECT * FROM t2 WHERE username LIKE 'li%'


            • 12、当数据量大时,制止利用where 1=1的条件。通常为了方便拼装查询条件,我们会默认利用该条件,数据库引擎会放弃索引进行全表扫描

              • SELECT * FROM t WHERE 1=1
              • 优化方式:用代码拼装sql时进行判断,没where加where,有where加and。

            • 13、创建索引后,查询时不会扫描全表,而会查询索引表锁定效果
            • 14、在数据库进行DML操纵的时间,除了维护数据表之外,还需要维护索引表,运维成本增长
            • 15、选用选择性高的字段作为索引,一般unique的选择性最高
            • 16、复合索引:选择性越高的排在越前面。(左前缀原则);
            • 17、如果查询条件中两个条件都是选择性高的,最好都建索引
            • 18、 数据范例出现隐式转换时也不会利用索引

              • 让我们对上一个例子中的表增长一个 AGE 索引。
              • CREATE TABLE `test_index_table` (
              • `id` int(11) NOT NULL AUTO_INCREMENT,
              • `name` varchar(45) DEFAULT NULL,
              • `birthday` datetime DEFAULT NULL,
              • `address` varchar(45) DEFAULT NULL,
              • `phone` varchar(45) DEFAULT NULL,
              • `note` varchar(45) DEFAULT NULL,
              • `age` varchar(11) DEFAULT NULL,
              • PRIMARY KEY (`id`),
              • KEY `NAME_ADDRESS` (`name`,`id`) USING BTREE,
              • KEY `AGE` (`age`) USING BTREE
              • ) ENGINE=InnoDB AUTO_INCREMENT=283 DEFAULT CHARSET=utf8
              • 实验利用下面的 sql 语句进行查询
              • explain SELECT * FROM test.test_index_table where age = 26
              • 由于表中的 age 是 VARCHAR 范例。而在 sql 语句中我们利用的是数字范例 26。MYSQL 默认会把输入的常量值进行转换以后才进行检索。现在我们通过 explain 看看这个语句的分析效果

            • 19、查看索引利用情况

              • show status like 'handler_read%';

            • 20、mysql查询只利用一个索引,因此如果where子句中已经利用了索引的话,那么order by中的列是不会利用索引的。    因此数据库默认排序可以符合要求的情况下不要利用排序操纵,尽量不要包含多个列的排序,如果需要最好给这些列建复合索引






免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊落一身雪

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表