MySQL:无法从特定分区中选择记录?

Sah*_*hah 5 mysql sql select partitioning find-in-set

我正在使用MySQL 5.6.我创建了一个包含366个分区的表,以便每天保存数据意味着在一年中我们最多有366天,因此我在该表上创建了366个分区.散列分区由整数列管理,每个记录存储1到366个整数列.

Report_Summary表:

CREATE TABLE `Report_Summary` (
  `PartitionsID` int(4) unsigned NOT NULL,
  `ReportTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `Amount` int(10) NOT NULL,
  UNIQUE KEY `UNIQUE` (`PartitionsID`,`ReportTime`),
  KEY `PartitionsID` (`PartitionsID`),
  KEY `ReportTime` (`ReportTime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED
/*!50100 PARTITION BY HASH (PartitionsID)
PARTITIONS 366 */
Run Code Online (Sandbox Code Playgroud)

我目前的查询:

SELECT DATE(RS.ReportTime) AS ReportDate, SUM(RS.Amount) AS Total
FROM Report_Summary RS
WHERE RS.ReportTime >= '2014-12-26 00:00:00' AND RS.ReportTime <= '2014-12-30 23:59:59' AND 
      RS.PartitionsID BETWEEN DAYOFYEAR('2014-12-26 00:00:00') AND DAYOFYEAR('2014-12-30 23:59:59')
GROUP BY ReportDate; 
Run Code Online (Sandbox Code Playgroud)

上面的查询是完全工作和使用分区P360P364获取数据.现在的问题是当我将fromDate传递给'2014-12-26'并且日期传递给'2015-01-01'然后上面的查询将无效.因为'2015-01-01'的那一天是1,所以我的条件失败了.

现在我尝试在IN运算符中传递值,然后它在查询下面的数据库检查中完美地工作:

SELECT DATE(RS.ReportTime) AS ReportDate, SUM(RS.Amount) AS Total
FROM Report_Summary RS
WHERE RS.ReportTime >= '2014-12-26 00:00:00' AND RS.ReportTime <= '2015-01-01 23:59:59' AND 
      RS.PartitionsID IN (360,361,362,363,364,365,1)
GROUP BY ReportDate; 
Run Code Online (Sandbox Code Playgroud)

为了生成上面的场景,我创建了一个函数并传递了两个日期并生成一个逗号分隔的ID字符串

SELECT GenerateRange('2014-12-26 00:00:00', '2015-01-01 23:59:59');
Run Code Online (Sandbox Code Playgroud)

其中重新发布数据为:

'360,361,362,363,364,365,366,1'
Run Code Online (Sandbox Code Playgroud)

我试图在我的查询中使用该函数,所以我更改了我的查询如下:

SELECT DATE(RS.ReportTime) AS ReportDate, SUM(RS.Amount) AS Total
FROM Report_Summary RS
WHERE RS.ReportTime >= '2014-12-26 00:00:00' AND RS.ReportTime <= '2015-01-01 23:59:59' AND 
      FIND_IN_SET(RS.PartitionsID, GenerateRange('2014-12-26 00:00:00', '2015-01-01 00:00:00'))
GROUP BY ReportDate; 
Run Code Online (Sandbox Code Playgroud)

然后我使用EXPLAIN PARTITION SELECT ...检查了上述查询的执行计划.我发现我的病情不会起作用.它使用所有分区来获取数据.我想只使用那些日期的特定分区.必须检查这些360,361,362,363,364,365,366,1分区是指p360p366p1.

为什么我的查询不起作用?这不是正确的方法来实现这个我想要的解决方案我怎样才能实现这一目标?

我从编码中知道我可以实现这个,但我必须编写一个查询来实现它.

谢谢...

Sah*_*hah 0

我得到了解决方案,因为我改变了在表中存储PartitionsId列的逻辑。最初我将DayOfYear(reportTime)列存储在PartitionsId列中。现在我通过存储TO_DAYS(reportTime)并存储到PartitionsId列中来更改该逻辑。

所以我的表结构如下:

CREATE TABLE `Report_Summary` (
  `PartitionsID` int(10) unsigned NOT NULL,
  `ReportTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `Amount` int(10) NOT NULL,
  UNIQUE KEY `UNIQUE` (`PartitionsID`,`ReportTime`),
  KEY `PartitionsID` (`PartitionsID`),
  KEY `ReportTime` (`ReportTime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED
/*!50100 PARTITION BY HASH (PartitionsID)
PARTITIONS 366 */

INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735928','2014-12-26 11:46:12','100');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735929','2014-12-27 11:46:23','50');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735930','2014-12-28 11:46:37','44');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735931','2014-12-29 11:46:49','15');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735932','2014-12-30 11:46:59','56');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735933','2014-12-31 11:47:22','68');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735934','2015-01-01 11:47:35','76');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735935','2015-01-02 11:47:43','88');
INSERT INTO `Report_Summary` (`PartitionsID`, `ReportTime`, `Amount`) VALUES('735936','2015-01-03 11:47:59','77');
Run Code Online (Sandbox Code Playgroud)

检查SQL FIDDLE 演示

我的查询是:

EXPLAIN PARTITIONS 
SELECT DATE(RS.ReportTime) AS ReportDate, SUM(RS.Amount) AS Total
FROM Report_Summary RS
WHERE RS.ReportTime >= '2014-12-26 00:00:00' AND RS.ReportTime <= '2015-01-01 23:59:59' AND 
      RS.PartitionsID BETWEEN TO_DAYS('2014-12-26 00:00:00') AND TO_DAYS('2015-01-01 23:59:59')
GROUP BY ReportDate; 
Run Code Online (Sandbox Code Playgroud)

上面的查询扫描我需要的特定分区,并且它还使用正确的索引。因此,在更改PartitionsId列的逻辑后,我找到了正确的解决方案。

感谢所有的回复,非常感谢大家的时间......