SQL查询优化-性能问题

时间:2019-01-22 14:18:50

标签: mysql sql query-performance

我有以下要优化的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,版本),并且每对夫妇都会影响一个层。

3 个答案:

答案 0 :(得分:0)

使用函数时,它将阻止使用索引,因此CONCAT(table1.id_item,table1.n_version_item)不会读取索引,除非其索引基于函数。但是,正如评论中提到的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) 

然后,您必须检查查询的查询计划正在使用什么索引(您可以使用列tiersid_itemn_version_item上的其他索引来开始索引)

答案 1 :(得分:0)

我想你想要

class Team extends ActiveRecord {
public $team_id; 
public $name;
public static $table = "teams";
public static $key = "team_id";
}

对于此版本,您希望在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 ); 上建立索引。

答案 2 :(得分:0)

如果将列隐藏在“函数”(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与空字符串)。