【发布时间】:2015-02-28 03:10:08
【问题描述】:
我正在使用 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 */
我当前的查询:
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;
上述查询运行良好,并使用分区 p360 到 p364 来获取数据。现在的问题是当我将 fromDate 传递给 '2014-12-26' 并将 toDate 传递给 '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;
为了生成上述场景,我创建了一个函数并传递了两个日期并生成了一个逗号分隔的 ID 字符串
SELECT GenerateRange('2014-12-26 00:00:00', '2015-01-01 23:59:59');
这将我的数据返回为:
'360,361,362,363,364,365,366,1'
我尝试在查询中使用该函数,因此我将查询更改如下:
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;
然后我使用 EXPLAIN PARTITION SELECT... 检查了上述查询的执行计划。我发现我的条件行不通。它使用所有分区来获取数据。我只想使用这些日期的特定分区。 必须只检查这些 360,361,362,363,364,365,366,1 分区表示 p360 到 p366 和 p1。
为什么我的查询不起作用?这不是实现这个的正确方法然后我想要解决方案我该如何实现这个?
我从编码中知道我可以实现它,但我必须编写一个查询来实现它。
谢谢...
【问题讨论】:
-
你想对你的请求做什么?你在等什么样的结果?
-
@akmozo 我想要一个工作查询,它将利用该条件所需的分区。但是我当前的查询条件是使用错误的所有分区。
-
我们是按 DAYOFYEAR 分区吗?您是否会有很多查询将一年中的某一天与前一年的某一天进行比较?如果不是,那么如果您的查询主要是顺序数据访问,那么您最好按 Year 或 YearMonth 或按顺序进行分区。
-
@BateTech 分区已经创建,所以我需要使用它,因为我无法更改它。
-
@SaharshShah 我已经更新了我的答案并添加了一个可能对您有用的“选项 3”,因为它在 where 子句中不使用
OR。
标签: mysql sql select partitioning find-in-set