zoukankan      html  css  js  c++  java
  • SQL优化

      

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

    理由:

    • 只取需要的字段,节省资源、减少网络开销。

    • select * 进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询。

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

    理由:

    • 加上limit 1后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。

    • 当然,如果name是唯一索引的话,是不必要加上limit 1了,因为limit的存在主要就是为了防止全表扫描,从而提高性能,如果一个语句本身可以预知不用全表扫描,有没有limit ,性能的差别并不大。

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

    应当使用两条SQL语句。在程序中控制。

    理由:

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

    对于or+没有索引的age这种情况,假设它走了userId的索引,但是走到age查询条件时,它还得全表扫描,也就是需要三步过程:全表扫描+索引扫描+合并 如果它一开始就走全表扫描,直接一遍扫描就完事。mysql是有优化器的,处于效率与成本考虑,遇到or条件,索引可能失效,看起来也合情合理。

    4、优化limit分页

    select * from articles where id >(select id from articles limit 170500,1) limit 500

    这种方法的好处是首先通过id索引快速定位到了分页数据的起始位置(避免了全文检索),并且用limit 方法快速获取了从起始位置往后的500个数据。

    最优:select * from articles where id between (select id from articles limit 170000,1) and (select id from articles limit 170500,1)

    between and的方法相当于也是利于id索引的优势,但是同时定位了分页的起始和终止的位置,截取了中间的信息,因此速度会更快.

    5:尽量避免在索引列上使用mysql的内置函数

    会导致索引失效

    6:应尽量避免在where子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫

    7:Inner join 、left join、right join,优先使用Inner join,如果是left join,左边表结果尽量小

    1. Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集
    2. left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。
    3. right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。

    都满足SQL需求的前提下,推荐优先使用Inner join(内连接),如果要使用left join,左边表数据结果尽量小,如果有条件的尽量放到左边处理。

    8:使用exists

    假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下SQL:

    1. select * from A where deptId in (select deptId from B);

    这样写等价于:

    先查询部门表B

    select deptId from B

    再由部门deptId,查询A的员工

    select * from A where A.deptId = B.deptId

    可以抽象成这样的一个循环:

    1. List<> resultSet ;

    2. for(int i=0;i<B.length;i++) {

    3. for(int j=0;j<A.length;j++) {

    4. if(A[i].id==B[j].id) {

    5. resultSet.add(A[i]);

    6. break;

    7. }

    8. }

    9. }

    显然,除了使用in,我们也可以用exists实现一样的查询功能,如下:

    1. select * from A where exists (select 1 from B where A.deptId = B.deptId);

    因为exists查询的理解就是,先执行主查询,获得数据后,再放到子查询中做条件验证,根据验证结果(true或者false),来决定主查询的数据结果是否得意保留。

    那么,这样写就等价于:

    select * from A,先从A表做循环

    select * from B where A.deptId = B.deptId,再从B表做循环.

    同理,可以抽象成这样一个循环:

    1. List<> resultSet ;

    2. for(int i=0;i<A.length;i++) {

    3. for(int j=0;j<B.length;j++) {

    4. if(A[i].deptId==B[j].deptId) {

    5. resultSet.add(A[i]);

    6. break;

    7. }

    8. }

    9. }

    数据库最费劲的就是跟程序链接释放。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。即mysql优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优。

    因此,我们要选择最外层循环小的,也就是,如果B的数据量小于A,适合使用in,如果B的数据量大于A,即适合选择exist

  • 相关阅读:
    每日一水 POJ8道水题
    编译和使用 MySQL C++ Connector
    j2ee model1模型完成分页逻辑的实现 详解!
    DB查询分析器访问EXCEL时,要在表名前后加上中括弧或双引号
    指向结构体变量的指针
    EOSS V3.0 企业运营支撑系统(基于RBAC原理的权限管理)
    MybatisGen1.0 Mybatis JavaBean Mapper生成工具
    The table name must be enclosed in double quotation marks or sqare bracket while accessing EXCEL by
    资源-Android:Android
    软件-开发软件:Android Studio
  • 原文地址:https://www.cnblogs.com/bulrush/p/12573958.html
Copyright © 2011-2022 走看看