繁体   English   中英

SQL查询优化-性能问题

[英]SQL Query optimization -performance issues

我有以下要优化的SQL查询:

select table1.tiers as col1, table1.id_item as col2 
from items table1 
where (table1.tiers is not null) 
  and table1.tiers<>''
  and table1.id_item = (select max(table2.id_item)
                        from items table2
                        where table1.tiers=table2.tiers) 
  and table1.n_version_item=(select max(table2.n_version_item) 
                             from items table2 
                             where table2.id_item=table1.id_item)

我尝试了这个:

select table1.tiers as col1, table1.id_item as col2 
from items table1 
where (table1.tiers is not null) 
  and table1.tiers<> '' 
  and CONCAT(table1.id_item,table1.n_version_item) =  (select CONCAT(max(table2.id_item),max(table2.n_version_item)) 
                                                       from items table2
                                                       where table2.id_item=table1.id_item 
                                                         and table1.tiers=table2.tiers)

但我没有得到相同的结果。 原始的第一个查询返回的行少于修改的行。 请注意,表项具有主键(id,版本),并且每对夫妇都会影响一个层。

使用函数时,它将阻止使用索引,因此CONCAT(table1.id_item,table1.n_version_item)除非基于函数的索引,否则CONCAT(table1.id_item,table1.n_version_item)不会读取索引。 但是,正如a_horse_with_no_name提到的a_horse_with_no_name ,您可以使用以下代码:

select itm.tiers as col1, itm.id_item as col2 
from items itm
where itm.tiers is not null 
  and itm.tiers<>''
  and (itm.id_item , itm.n_version_item)= (select 
 max(item_sub.id_item),max(item_sub.n_version_item)
                        from items item_sub
                        where itm.tiers=item_sub.tiers) 

然后,您必须检查查询的查询计划,正在使用什么索引(可以在id_itemn_version_item上使用列tiers和其他索引来启动索引)

我想你要:

select i.tiers as col1, i.id_item as col2 
from items i 
where i.tiers is not null and  -- redundant, but I'm leaving it in
      i.tiers <> '' 
      (id_item, n_version_item) = (select i2.id_item, max(i2.n_version_item)
                                   from items i2
                                   where i2.tiers = i.tiers
                                   order by i2.id_item desc, i2.n_version_item desc
                                   limit 1
                                  );

对于此版本,您需要在items(tiers, id_item, n_version_item)上建立索引。

如果将列隐藏在“函数”( CONCATDATE等)中,则不能使用索引来提高性能。 这消除了您考虑的第二个版本。

与此相关的是使用“行构造器”(请参阅​​a_horse_with_no_name的注释)。 从历史上看,它们的优化很差; 避免他们。 我指的是WHERE (a,b) IN ( (1,2), ...)或其他变体。

现在,让我们剖析

  and table1.id_item = (select max(table2.id_item)
                    from items table2
                    where table1.tiers=table2.tiers) 

table2需要按该顺序的INDEX(tiers, id_item) 这样,子查询就非常快。 其他子查询需要INDEX(id_item, n_version_item)其余的子查询:

  and table1.id_item = <<value>>

现在让我们看整个

where (table1.tiers is not null) 
  and  table1.tiers<>''
  and  table1.id_item = <<value>>
  and  table1.n_version_item = <<value>>

=易于优化; 其他不是。 所以我们来建立

INDEX(id_item, n_version_item,  -- in either order
      tiers)    -- last

通过使用我指定的顺序,您可以避免还需要上面提到的INDEX(id_item, n_version_item)

(如果您提供了SHOW CREATE TABLE ,它将有所帮助;我需要知道PK是什么,以及其他一些东西。)

另外,这些索引将是“覆盖索引”。

最后一点(小调):

where (table1.tiers is not null) 
  and  table1.tiers<>''

最好仅根据您所指示的内容决定一种编码( NULL与空字符串)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM