范围查询未在mysql

时间:2016-12-08 04:59:39

标签: mysql optimization

我正在尝试优化我们用于生成报告的查询。 我认为我做了很好的优化到一些扩展。 以下是原始查询:

select trat.asset_name as group_name,trat.name as sub_group_name,
       trat.asset_id as group_id,
       if(trat.cause_task_type='AccessRequest',true,false) as is_request_task,
       '' as grouped_on,
       concat(trat.asset_name,' - {0} (',count(*),')') as table_heading
    from t_remote_agent_tasks trat
    where trat.status in ('completed','failedredundant')
      and trat.name not in ('collect-data','update-conn-params')
    group by trat.asset_name, trat.name
    order by field(trat.name,'create-account','change-attr',
                             'add-member-to-group',
                             'grant-access','disable-account','revoke-access',
                             'remove-member-from-group','update-license')  

当我在Extra列中看到执行情况时,它说使用where,Using Temporary,filesort。

所以我像这样优化查询

select  trat.asset_name as group_name,trat.name as sub_group_name,
        trat.asset_id as group_id,
        if(trat.cause_task_type='AccessRequest',true,false) as is_request_task,
        '' as grouped_on,
        concat(trat.asset_name,' - {0} (',count(*),')') as table_heading
    from t_remote_agent_tasks trat
    where trat.status in ('completed','failedredundant')
      and trat.name not in ('collect-data','update-conn-params')
    group by trat.asset_name,trat.name
    order by null

这给了我执行计划,使用where,使用临时。所以filesort不再使用,并且没有额外的开销,因为优化器不需要排序,这将在分组期间处理。

我再次前进并按照组中提到的相同顺序创建索引(这很重要或优化不会发生),即创建索引(trat.asset_name,trat.name)。 现在这个优化让我只在额外的列中使用。此外,查询执行时间推断了近一半(早先是0.568秒,现在是0.345秒,虽然每次都变化但在这个范围内或多或少都不一样)。

现在我想优化范围查询,在查询的一部分下面

    trat.status in ('completed','failedredundant')
and trat.name not in ('collect-data','update-conn-params')

我正在阅读mysl reference guide to optimize range query,其中说不在范围查询中,所以我在这样的查询中进行了修改

    trat.status in ('completed','failedredundant')
and trat.name in ('add-member-to-group','change-attr','create-account',
                  'disable-account','grant-access', 'remove-member-from-group',
                  'update-license')

但它没有显示Extra的任何改进(我的意思是使用索引应该在那里,它仍然显示使用where)。 我还尝试将两个范围部分拆分为联合(这将改变查询结果,但仍然没有改进执行计划)

我想要更多关于如何优化此查询的帮助,主要是范围部分(部分)。 如果我需要进行任何其他优化?

感谢您的时间,提前致谢

编辑1我忘了提到我在trat.status上也有索引,所以下面是索引

  1. (trat.asset_name,trat.name)
  2. (trat.status)

1 个答案:

答案 0 :(得分:0)

几乎在所有情况下,SELECT中只使用一个索引。所以,一个人必须拥有最好的。

前两个查询的可能从同一个'复合'索引中受益最多:

INDEX(asset_name, name)

通常,人们会尝试处理索引中的WHERE条件,但它们看起来不适合索引。 (更多讨论如下。)第二个选择是GROUP BY,我推荐。但是,由于(在第一种情况下)ORDER BYGROUP BY不同,因此必须为GROUP BY的输出创建一个tmp表,以便可以根据到ORDER BY。 (GROUP BY也可能有tmp和排序;我无法分辨。)

“使用索引”表示使用“覆盖”索引。 “覆盖”索引是一个复合索引,其中包含SELECT任何地方使用的所有列。那将是大约5列,并且尝试可能不明智。 (更多信息如下。)

另外需要注意的是,即便是这样的事情:

WHERE x IN (11,22)
GROUP BY y

无法使用任何索引同时处理WHEREGROUP BY。因此,您的查询无法同时使用它们(除了“覆盖”)。

覆盖指数在使用时仅部分有用。它说所有工作都是在索引的BTree中完成的。但这可能包括完整的索引扫描 - 这并不比全表扫描快得多。这是反对推荐“覆盖”的另一个论点。

在某些情况下,INOR可以通过将其变为UNION来加速:

( SELECT ... WHERE status in ('completed') )
UNION ALL
( SELECT ... WHERE status in ('failedredundant') )

但这只会让你偶然发现NOT IN(...)条款,这比IN更糟糕。

找到最佳索引的目的是找到一个连续坐在BTree中的行(在索引和/或表中)。

要对此查询进行任何进一步改进,可能需要重新考虑架构 - 它似乎强迫您拥有INNOT INFIELD等其他难题优化结构。