SQL VIEW简化/解决方案更快查询

时间:2013-10-28 20:26:43

标签: mysql sql mariadb

我正在尝试分解并重新编写一个由已经过时的开发人员创建的视图。查询需要三个以上的分钟才能访问,我假设来自所有的CONCAT。

CREATE VIEW `active_users_over_time` AS 
select 
   `users_activity`.`date` AS `date`,
   time_format(
        addtime( 
            concat(`users_activity`.`date`,' ',`users_activity`.`time`),
            concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0')
        ),'%H:%i:%s') AS `time`,
   `users_activity`.`username` AS `username`,
   count(addtime(concat(`users_activity`.`date`,' ',`users_activity`.`time`),
   concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0'))) AS `checkouts` 
from `users_activity` 
group by 
   concat(
       addtime(
             concat(`users_activity`.`date`,' ',`users_activity`.`time`),
             concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0')
       ),
       `users_activity`.`username`);

数据来自SQL表:

CREATE TABLE `users_activity` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `featureid` smallint(5) unsigned NOT NULL,
  `date` date NOT NULL,
  `time` time NOT NULL,
  `duration_checkout` int unsigned NOT NULL,
  `update_date` date NOT NULL,
  `username`  varchar(255) NOT NULL,
  `checkout` smallint(5) unsigned NOT NULL,
  `licid` smallint(5) unsigned NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `featureid_licid_username` (`featureid`,`licid`,`date`,`time`,`username`),
  FOREIGN KEY(featureid) REFERENCES features(id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

我很难确定究竟需要什么以及什么不需要。

有人有什么想法吗?感谢。

2 个答案:

答案 0 :(得分:2)

我认为这会完成原始查询的所有操作,跳过一堆冗余步骤:

select `date`
, `time`
, `username`
, count(1) as `checkouts`
from
(
  select 
   `users_activity`.`date` AS `date`
   ,time_format(
     addtime(`users_activity`.`date`,`users_activity`.`time`)
     + interval `users_activity`.`duration_checkout` second
     ,'%H:%i:%s'
   ) AS `time`
   ,`users_activity`.`username` AS `username`
  from `users_activity` 
) x
group by `username`, `date`, `time`

您可能还想查看表中的索引以查看是否可以在其他位置进行优化(例如,如果您还没有关于用户名和日期字段的索引,那么您将获得很多好处这个查询通过添加一个)。

答案 1 :(得分:-2)

您可以从重写GROUP BY clase开始:

group by 
   concat(
       addtime(
             concat(`users_activity`.`date`,' ',`users_activity`.`time`),
             concat('0 ',sec_to_time(`users_activity`.`duration_checkout`),'.0')
       ),
       `users_activity`.`username`);

到这一个:

GROUP BY `users_activity`.`date`,
         `users_activity`.`time`,
         `users_activity`.`duration_checkout`,
         `users_activity`.`username`

此更改应该可以稍微节省将日期转换为字符串并将其连接起来,并且查询结果不应更改。

然后,您可以考虑在GROUP BY列上创建复合索引 根据此链接:http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html

  

使用GROUP BY索引的最重要前提条件是所有GROUP BY列引用同一索引的属性

这意味着,如果我们创建以下索引:

CREATE INDEX idx_name ON `users_activity`(
    `date`,`time`,`duration_checkout`,`username`
);

然后MySql可能会使用它来优化GROUP BY(但不能保证)。