2014-10-16 74 views
1

首先,如果使用的术语不正确,则表示抱歉。我不是一个mySQL专业人员。将索引添加到生成的列

我有这样的一个表:

CREATE TABLE `accesses` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `time` int(11) DEFAULT NULL, 
    `accessed_at` datetime DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `index_accesses_on_accessed_at` (`accessed_at`) 
) ENGINE=InnoDB AUTO_INCREMENT=9278483 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

此表中有10.000.000行。我用它来生成图表,用这样的查询:

SELECT SUM(time) AS value, DATE(created_at) AS date 
FROM `accesses` 
GROUP BY date; 

这个查询很长(超过1分钟)。我在做很多其他的查询(与AVGMINMAX代替SUM,或在特定日期或一个月WHERE,或GROUP BY HOUR(created_at),等...)

我想优化。 我最好的想法是添加几个列,冗余,如DATE(created_at),HOUR(created_at),MONTH(created_at),然后添加一个索引。

...这个解决方案很好,还是有其他的吗?

问候

+0

给出完整的表格声明可能是明智的,输出结果如下:'SHOW CREATE TABLE accesses' – NDM 2014-10-16 15:16:58

+0

对于这样的简单选择查询,1分钟就是海拉了,即使有你拥有的记录数量也是如此。我会把这个问题提交给[DatabaseAdministrators](http://dba.stackexchange.com/)。 – Alternatex 2014-10-16 15:19:23

+0

好吧,他在10万条记录上做了“组”和“总和”,没有限制结果集... – NDM 2014-10-16 15:21:37

回答

2

是的,它可以是永久的列存储冗余数据与索引优化某些查询的优化。这是非规范化的一个例子。

根据数据量和查询频率,这可能是一个重要的加速(@Marshall Tigerus太低,恕我直言)。

我测试了这一点,通过运行EXPLAIN:

mysql> explain SELECT SUM(time) AS value, DATE(created_at) AS date FROM `accesses` GROUP BY date\G      *************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: accesses 
    partitions: NULL 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: Using temporary; Using filesort 

忽视的事实是,表是我在试空。重要的部分是Using temporary; Using filesort,这些操作是昂贵的操作,尤其是如果您的临时表变得如此之大以至于MySQL无法将其放入内存。

我加了一些列和索引他们:

mysql> alter table accesses add column cdate date, add key (cdate), 
    add column chour tinyint, add key (chour), 
    add column cmonth tinyint, add key (cmonth); 

mysql> explain SELECT SUM(time) AS value, cdate FROM `accesses` GROUP BY cdate\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: accesses 
    partitions: NULL 
     type: index 
possible_keys: cdate 
      key: cdate 
     key_len: 4 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: NULL 

临时表和文件排序就走了,因为MySQL知道它可以做一个索引扫描处理以正确的顺序行。

+0

感谢您的完整答案。我的查询完成时间少于400毫秒。很好! – pierallard 2014-10-17 14:45:27

+0

很高兴帮助!现在,您必须在插入和更新时编写触发器,以使生成的列与created_date保持同步。 – 2014-10-17 16:42:46