• SQL语句性能优化


    1、查询 SQL 尽量不要使用 select *,而是 select 具体字段

    反例子:

    select * from sys_user

    正例子:

    select idname from sys_user

    理由如下:

    • 只取需要的字段,节省资源、减少网络开销。
    • select * 进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询。

    2、如果知道查询结果只有一条或者只要最大/最小一条记录,建议用 limit 1

    假设现在有 sys_user 员工表,要找出一个名字叫 jay 的人:

    CREATE TABLE `sys_user` (
      `id` int(11) NOT NULL,
      `name` varchar(255) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `date` datetime DEFAULT NULL,
      `sex` int(1) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    反例:

    select idname from sys_user where name='jay' 

    正例:

    select idname from sys_user where name='jay' limit 1

    理由如下:

    • 加上 limit 1 后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。
    • 当然,如果 name 是唯一索引的话,是不必要加上 limit 1 了,因为 limit 的存在主要就是为了防止全表扫描,从而提高性能,如果一个语句本身可以预知不用全表扫描,有没有 limit ,性能的差别并不大。

    3、应尽量避免在 where 子句中使用 or 来连接条件

    新建一个 user 表,它有一个普通索引 userId,表结构如下:

    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `userId` int(11) NOT NULL,
      `age` int(11) NOT NULL,
      `name` varchar(255) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `idx_userId` (`userId`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    假设现在需要查询 userid 为 1 或者年龄为 18 岁的用户,很容易有以下 SQL。

    反例:

    select * from user where userid=1 or age =18 

    正例:

    //使用union all
    select * from user where userid=1 
    union all 
    select * from user where age = 18

    //或者分开两条sql写:
    select * from user where userid=1
    select * from user where age = 18

    理由:使用 or 可能会使索引失效,从而全表扫描。

    对于 or+没有索引的 age 这种情况,假设它走了 userId 的索引,但是走到 age 查询条件时,它还得全表扫描,也就是需要三步过程:全表扫描+索引扫描+合并,如果它一开始就走全表扫描,直接一遍扫描就完事。

    MySQL 是有优化器的,处于效率与成本考虑,遇到 or 条件,索引可能失效,看起来也合情合理。

    4、优化 limit 分页

    我们日常做分页需求时,一般会用 limit 实现,但是当偏移量特别大的时候,查询效率就变得低下。

    反例:

    select idname,age from sys_user limit 1000010 

    正例:

    //方案一 :返回上次查询的最大记录(偏移量)
    select idname from sys_user where 

  • 相关阅读:
    Python报错ImportError: cannot import name ‘CREATE_NO_WINDOW‘
    oracle11g体系结构
    C++模拟OpenGL库——图形学状态机接口封装(二):基于状态机接口的画线&画三角形
    python学习--特殊方法和属性
    C++11新特性(lambda,可变参数模板,包装器,bind)
    【JAVA程序设计】(C00086)基于Servlet+jsp的学生信息管理系统
    JavaScript中的键值对数组Map对象的使用总结
    C++ 多维数组
    Mac的Safari浏览器如何打开检查元素【网页控制台】
    【数据结构】&&【C++】封装哈希表模拟实现unordered_map和unordered_set容器
  • 原文地址:https://blog.csdn.net/tzweilai/article/details/134247361