数据库教程

如何写出高性能SQL

精准像素 2020-11-26 人阅读

定量遍历次数

在编写一条查询语句的时候,可以依据你要查询数据表的数据总量,估算一下这条查询大致需要遍历多少行数据:

如果遍历行数在百万以内的,只要不是每秒钟都要执行几十上百次的频繁查询,可以认为是安全的。

遍历数据行数在几百万的,查询时间最少也要几秒钟,你就要仔细考虑有没有优化的办法。

遍历行数达到千万量级和以上的,我只能告诉你,这种查询就不应该出现在你的系统中。当然我们这里说的都是在线交易系统,离线分析类系统另说。

遍历行数在千万左右,是 MySQL 查询的一个坎儿。MySQL 中单个表数据量,也要尽量控制在一千万条以下,最多不要超过二三千万这个量级。原因也很好理解,对一个千万级别的表执行查询,加上几个 WHERE 条件过滤一下,符合条件的数据最多可能在几十万或者百万量级,这还可以接受。但如果再和其他的表做一个联合查询,遍历的数据量很可能就超过千万级别了。所以,每个表的数据量最好小于千万级别。

避免全表索引

绝大多数情况下,我们编写的查询语句,都应该使用索引,避免去遍历整张表,也就是通常说的,避免全表扫描。你在每次开发新功能,需要给数据库增加一个新的查询时,都要评估一下,是不是有索引可以支撑新的查询语句,如果有必要的话,需要新建索引来支持新增的查询。

增加索引付出的代价是,会降低数据插入、删除和更新的性能。这个也很好理解,增加了索引,在数据变化的时候,不仅要变更数据表里的数据,还要去变更每个索引。所以,对于更新频繁并且对更新性能要求较高的表,可以尽量少建索引。而对于查询较多更新较少的表,可以根据查询的业务逻辑,适当多建一些索引。

分析 SQL 执行计划

在 MySQL 中使用执行计划也非常简单,只要在你的 SQL 语句前面加上 EXPLAIN 关键字,然后执行这个查询语句就可以了。

比如有一个用户表,包含用户 ID、姓名、部门编号和状态这几个字段:

我们希望查询某个二级部门下的所有人,查询条件就是,部门代号以 00028 开头的所有人。下面这两个 SQL,他们的查询结果是一样的,都满足要求,但是,哪个查询性能更好呢?

SELECT * FROM user WHERE left(department_code, 5) = '00028';SELECT * FROM user WHERE department_code LIKE '00028%';

我们分别查看一下这两个 SQL 的执行计划:

row 列:

MySQL 预估执行这个 SQL 可能会遍历的数据行数。第一个 SQL 遍历了四千多行,这就是整个 User 表的数据条数;第二个 SQL 只有 8 行,这 8 行其实就是符合条件的 8 条记录。显然第二个 SQL 查询性能要远远好于第一个 SQL。

type 列:

表示这个查询的访问类型。ALL 代表全表扫描,这是最差的情况。range 代表使用了索引,在索引中进行范围查找,因为第二个 SQL 语句的 WHERE 中有一个 LIKE 的查询条件。如果直接命中索引,type 这一列显示的是 index。如果使用了索引,可以在 key 这一列中看到,实际上使用了哪个索引。

总结

在开发阶段,衡量一个 SQL 查询语句查询性能的手段是,估计执行 SQL 时需要遍历的数据行数。遍历行数在百万以内,可以认为是安全的 SQL,百万到千万这个量级则需要仔细评估和优化,千万级别以上则是非常危险的。为了减少慢 SQL 的可能性,每个数据表的行数最好控制在千万以内。 索引可以显著减少查询遍历数据的数量,所以提升 SQL 查询性能最有效的方式就是,让查询尽可能多的命中索引,但索引也是一把双刃剑,它在提升查询性能的同时,也会降低数据更新的性能。 对于复杂的查询,最好使用 SQL 执行计划,事先对查询做一个分析。在 SQL 执行计划的结果中,可以看到查询预估的遍历行数,命中了哪些索引。执行计划也可以很好地帮助你优化你的查询语句。

相关推荐
  • sql教程
  • 数据库查询
  • 帝国CMS批量替换栏目路径SQL

    将栏目路径清空SQL语句UPDATE phome_enewsclass SET classpath='';UPDATE phome_enewsclass SET classpath=concat(classpath,'html/',classid);

    帝国cms教程 98 2年前
  • SQL清空某字段的值

    网上找了好多文章才发现,主要是好多都是错了,试了很多。最开始找到是这段,网上都说等于null是对的update tablename set temp=null但测试等于null是不行的,直接报错。update px_dp_tagsadd set py="";网上都说不能等于空,但我测试发现等于等于空才是对的...

    经验分享 993 2年前
  • SQL批量替换字段字符语句
    SQL批量替换字段字符语句

    SQL产品图最近优化网站结构遇到的问题,分享给大家。要求是需要把内容字段的H4标签用SQL语句批量替换成b标签,利于网站整体优化。在网上学习了这段代码,测试可以使用。SQL批量替换字段语句示例update...

    数据库教程 68 2年前
  • 数据库SQL查询方法集合

    数据库几种SQL查询方法集合,带注释,简单明了。查询某个表SELECT TABLENAME;查询多个表从某库 SELECT TABLENAME1,TABLENAME2,TABLENAME3 FROM DATABASE;查询全部列从某库SELECT * FROM...

    数据库教程 17 3个月前
  • SQL多种条件查询方法集合

    查询值等于2.50的行select column1,column2 from tables where column1=2.50;查询字符等于‘fuses’的行select column1,column2 from tables where column1=&#39;fuses&#39;;查询值小于10的行select column1,column2 from tables where column1<10;查...

    数据库教程 16 3个月前
  • SQL新手入门SELECT数据库查询语句

    SELECT语义SELECT 语句用于从数据库中选取数据。结果被存储在一个结果表中,称为结果集。SELECT语法示例SELECT column_name,column_name FROM table_name;SELECT * FROM table_name;下面的 SQL 语句从 "Websites" 表中选取 "name" 和 "country" 列:SEL...

    数据库教程 37 9个月前