zoukankan      html  css  js  c++  java
  • MySQL

    1. LIMIT 语句

    分页查询是最常用的场景之一,但也通常也是最容易出问题的地方。比如:

    SELECT * FROM table_name WHERE type = 'type' AND name = 'name' ORDER BY create_time LIMIT 1000, 10;

    一般DBA想到的办法是在type, name, create_time字段上加组合索引。这样条件排序都能有效的利用到索引,性能迅速提升。

    当 LIMIT 子句变成 “LIMIT 1000000,10” 时,还是慢为啥?因为数据库也并不知道第1000000条记录从什么地方开始,即使有索引也需要从头计算一次。

    在前端数据浏览翻页,或者大数据分批导出等场景下,是可以将上一页的最大值当成参数作为查询条件的。比如:

    SELECT * FROM table_name WHERE type = 'type' AND name = 'name' AND create_time > '2016-06-20 12:00:00' ORDER BY create_time limit 10;

    在新设计下查询时间基本固定,不会随着数据量的增长而发生变化。

    2.混合排序

    MySQL不能利用索引进行混合排序。但在某些场景,还是有机会使用特殊方法提升性能的。

    SELECT * FROM my_order o INNER JOIN my_appraise a ON a.orderid = o.id ORDER BY a.is_reply ASC, a.appraise_time DESC LIMIT 0, 20

    执行计划显示为全表扫描,由于is_reply只有0和1两种状态,我们按照下面的方法重写后,执行时间从1.58秒降低到2毫秒。

    SELECT * FROM ((SELECT * FROM my_order o INNER JOIN my_appraise a ON a.orderid = o.id AND is_reply = 0 ORDER BY appraise_time DESC LIMIT 0, 20) UNION ALL (SELECT * FROM my_order o INNER JOIN my_appraise a ON a.orderid = o.id AND is_reply = 1 ORDER BY appraise_time DESC LIMIT 0, 20)) t ORDER BY is_reply ASC, appraisetime DESC LIMIT 20;

     3.EXISTS语句

    MySQL对待EXISTS子句时,仍然采用嵌套子查询的执行方式。

    SELECT * FROM my_neighbor n LEFT JOIN my_neighbor_apply sra ON n.id = sra.neighbor_id AND sra.user_id = 'xxx' WHERE n.topic_status < 4 AND EXISTS(SELECT 1 FROM message_info m WHERE n.id = m.neighbor_id AND m.inuser = 'xxx') AND n.topic_type <> 5 
    去掉exists更改为join,能够避免嵌套子查询,将执行时间从1.93秒降低为1毫秒。
    SELECT * FROM my_neighbor n INNER JOIN message_info m ON n.id = m.neighbor_id AND m.inuser = 'xxx' LEFT JOIN my_neighbor_apply sra ON n.id = sra.neighbor_id AND sra.user_id = 'xxx' WHERE n.topic_status < 4 AND n.topic_type <> 5

     4.条件下推

    外部查询条件不能够下推到复杂的视图或子查询的情况有:

    1.聚合子查询;

    2.含有LIMIT的子查询;

    3.UNION 或UNION ALL子查询;

    4.输出字段中的子查询;

    如下面的语句,从执行计划可以看出其条件作用于聚合子查询之后:

    SELECT * FROM (SELECT target, Count(*) FROM operation GROUP BY target) t WHERE target = 'rm-xxxx';

    确定从语义上查询条件可以直接下推后,重写如下:

    SELECT target, Count(*) FROM operation WHERE target = 'rm-xxxx' GROUP BY target;

    sql语句不是写的越少执行效率越高,要考虑的因素是比较多的,我们是为了更快的拿到数据,而不是简单的写出sql语句。数据库编译器产生执行计划,决定着SQL的实际执行方式。了解数据库编译器的特性,才能避规其短处,写出高性能的SQL语句。

    在设计数据模型以及编写SQL语句时,要把算法的思想或意识带进来。编写复杂SQL语句要养成使用WITH语句的习惯。简洁且思路清晰的SQL语句也能减小数据库的负担 。

    原文链接:https://yq.aliyun.com/articles/72501?utm_content=m_14899

    每日一学习,才会有更多的进步

  • 相关阅读:
    hihocoder 1049 后序遍历
    hihocoder 1310 岛屿
    Leetcode 63. Unique Paths II
    Leetcode 62. Unique Paths
    Leetcode 70. Climbing Stairs
    poj 3544 Journey with Pigs
    Leetcode 338. Counting Bits
    Leetcode 136. Single Number
    Leetcode 342. Power of Four
    Leetcode 299. Bulls and Cows
  • 原文地址:https://www.cnblogs.com/pfdltutu/p/9019350.html
Copyright © 2011-2022 走看看