MySql日历表和表演

时间:2017-07-31 08:34:22

标签: mysql performance join calendar

对于我正在进行的项目,我有一个包含两个日期的表,这意味着一系列日期,我需要一种方法来在两个日期之间每天“乘以”我的行。

所以例如我开始2017-07-10,结束2017-07-14 2017-07-10,2017-07-11,2017-07-12,2017-07-13我需要有4条线路

为了做到这一点,我发现这里有人提到使用“日历表”,其中包含多年的所有日期。

所以我建造它,现在我有这两个简单的表:

CREATE TABLE `time_sample` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `start` varchar(16) DEFAULT NULL,
  `end` varchar(16) DEFAULT NULL,
  PRIMARY KEY (`societa_id`),
  KEY `start_idx` (`start`),
  KEY `end_idx` (`end`)
) ENGINE=MyISAM AUTO_INCREMENT=222 DEFAULT CHARSET=latin1;

此表包含我的日期范围,开始和结束都已建立索引,主键是增量int。 样本行:

id  start   end
1   2015-05-13  2015-05-18

第二张表:

CREATE TABLE `time_dimension` (
  `id` int(11) NOT NULL,
  `db_date` date NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `td_dbdate_idx` (`db_date`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

对于未来许多年的每一天都有一个索引日期。 样本行:

id  db_date
20120101    2012-01-01

现在,我加入了联盟:

select * from time_sample s join time_dimension t on (t.db_date >= start and t.db_date < end);

这需要3毫秒。即使我的第一张桌子是巨大的,这个查询也会非常快(我看到的最多是50毫秒,有很多记录)。

我遇到的问题是在分组结果时(我需要将它们分组为我的应用程序):

select * from time_sample s join time_dimension t on (t.db_date >= start and t.db_date < end) group by db_date;

这需要一秒多的时间,第一个表中没有那么多行,而且显着增加。为什么会发生这种情况?我该如何避免这种情况?

更改数据类型没有用,让第二个表只有一列没有帮助。

我可以提出建议吗:(

1 个答案:

答案 0 :(得分:0)

我无法复制这个结果......

我有一个包含大量日期的日历表:calendar(dt)其中dt是PRIMARY KEY DATE数据类型。

$refs

即使有了GROUP BY,我也很难重现这个问题。这是一个简单的COUNT ...

DROP TABLE IF EXISTS time_sample;

CREATE TABLE time_sample (
  id int(11) NOT NULL AUTO_INCREMENT,
  start date not NULL,
  end date null,
  PRIMARY KEY (id),
  KEY (start,end)
);

INSERT INTO time_sample (start,end) VALUES  ('2010-03-13','2010-05-09);

SELECT * 
  FROM calendar x 
  JOIN time_sample y 
    ON x.dt BETWEEN y.start AND y.end;
+------------+----+------------+------------+
| dt         | id | start      | end        |
+------------+----+------------+------------+
| 2010-03-13 |  1 | 2010-03-13 | 2010-05-09 |
| 2010-03-14 |  1 | 2010-03-13 | 2010-05-09 |
| 2010-03-15 |  1 | 2010-03-13 | 2010-05-09 |
| 2010-03-16 |  1 | 2010-03-13 | 2010-05-09 |
...
| 2010-05-09 |  1 | 2010-03-13 | 2010-05-09 |
+------------+----+------------+------------+
58 rows in set (0.10 sec)

EXPLAIN
SELECT * FROM calendar x JOIN time_sample y ON x.dt BETWEEN y.start AND y.end;
+----+-------------+-------+--------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+--------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | y     | system | start         | NULL    | NULL    | NULL |    1 |                          |
|  1 | SIMPLE      | x     | range  | PRIMARY       | PRIMARY | 3       | NULL |   57 | Using where; Using index |
+----+-------------+-------+--------+---------------+---------+---------+------+------+--------------------------+
2 rows in set (0.00 sec)
相关问题