1

我正在尝试分解并重新编写一个由早已离开的开发人员创建的视图。查询需要超过三分钟才能访问,我假设来自所有 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;

我很难区分到底需要什么,不需要什么。

有人有想法么?谢谢。

4

2 回答 2

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`

您可能还想查看表上有哪些索引,以查看是否可以在其他地方进行优化(例如,如果您还没有用户名和日期字段的索引,您将通过此查询获得很多好处添加一个)。

于 2013-10-28T23:38:09.197 回答
-2

You can start from rewriting GROUP BY clase from this:

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

to this one:

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

This change should give some slight savings on converting dates to strings and concatenating them,
and the result of the query shouldn't change.

Then you may consider creating a composite index on GROUP BY columns.
According to this link: http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html

The most important preconditions for using indexes for GROUP BY are that all GROUP BY columns reference attributes from the same index

It means, that if we create the following index:

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

then MySql might use it to optimize GROUP BY (but there is no guarantee).

于 2013-10-28T23:45:07.197 回答