zoukankan      html  css  js  c++  java
  • 使用变量,并且消除嵌套查询

    set @a:='1000-01-01 00:00:00';  
    set @b:=' ';  
    truncate t_target;  
    insert into t_target  
    select * from t_source force index (idx_sort)  
     where (@a!=created_time or @b!=item_name) and (@a:=created_time) is not null and (@b:=item_name) is not null  
     order by created_time,item_name;  
            本次用时12秒,查询计划如下:

    mysql> explain select * from t_source force index (idx_sort)  
        ->  where (@a!=created_time or @b!=item_name) and (@a:=created_time) is not null and (@b:=item_name) is not null  
        ->  order by created_time,item_name;
    +----+-------------+----------+------------+-------+---------------+----------+---------+------+--------+----------+-------------+
    | id | select_type | table    | partitions | type  | possible_keys | key      | key_len | ref  | rows   | filtered | Extra       |
    +----+-------------+----------+------------+-------+---------------+----------+---------+------+--------+----------+-------------+
    |  1 | SIMPLE      | t_source | NULL       | index | NULL          | idx_sort | 94      | NULL | 997281 |    99.00 | Using where |
    +----+-------------+----------+------------+-------+---------------+----------+---------+------+--------+----------+-------------+
    1 row in set, 3 warnings (0.00 sec)
            该语句具有以下特点:

    消除了嵌套子查询,只需要对t_source表进行一次全索引扫描,查询计划已达最优。
    无需distinct二次查重。
    变量判断与赋值只出现在where子句中。
    利用索引消除了filesort。
            在MySQL 8之前,该语句是单线程去重的最佳解决方案。仔细分析这条语句,发现它巧妙地利用了SQL语句的逻辑查询处理步骤和索引特性。一条SQL查询的逻辑步骤为:

    执行笛卡尔乘积(交叉连接)
    应用ON筛选器(连接条件)
    添加外部行(outer join)
    应用where筛选器
    分组
    应用cube或rollup
    应用having筛选器
    处理select列表
    应用distinct子句
    应用order by子句
    应用limit子句
            每条查询语句的逻辑执行步骤都是这11步的子集。拿这条查询语句来说,其执行顺序为:强制通过索引idx_sort查找数据行 -> 应用where筛选器 -> 处理select列表 -> 应用order by子句。

            为了使变量能够按照created_time和item_name的排序顺序进行赋值和比较,必须按照索引顺序查找数据行。这里的force index (idx_sort)提示就起到了这个作用,必须这样写才能使整条查重语句成立。否则,因为先扫描表才处理排序,因此不能保证变量赋值的顺序,也就不能确保查询结果的正确性。order by子句同样不可忽略,否则即使有force index提示,MySQL也会使用全表扫描而不是全索引扫描,从而使结果错误。索引同时保证了created_time,item_name的顺序,避免了文件排序。force index (idx_sort)提示和order by子句缺一不可,索引idx_sort在这里可谓恰到好处、一举两得。

            查询语句开始前,先给变量初始化为数据中不可能出现的值,然后进入where子句从左向右判断。先比较变量和字段的值,再将本行created_time和item_name的值赋给变量,按created_time、item_name的顺序逐行处理。item_name是字符串类型,(@b:=item_name)不是有效的布尔表达式,因此要写成(@b:=item_name) is not null。

            最后补充一句,这里忽略了“insert into t_target select * from t_source group by created_time,item_name;”的写法,因为它受“sql_mode='ONLY_FULL_GROUP_BY'”的限制。
    ---------------------

  • 相关阅读:
    html5语法
    Addthis使用
    css font-weight原理
    css3 background
    jquery对标签属性操作
    给textarea添加背景图
    label的for属性
    css3 text-shadow
    z-index堆叠规则
    css3 @font-face
  • 原文地址:https://www.cnblogs.com/hyhy904/p/11311221.html
Copyright © 2011-2022 走看看