MySQL - 关于 table 分区/子分区的说明
MySQL - clarification on table partition / subpartition
我有一个 table,里面有大约 3 亿条记录(仅 60 天)。 table 结构非常简单..
它有 12 列,其中 4 列是索引的:
LogTime - DateTime
RegionID - Integer
ProvinceID - Integer
CityID - Integer
还有一个唯一索引:
UNIQUE INDEX UI_IDX (`LogTime`, `RegionID`, `ProvinceID`, `CityID`);
其余字段只是主要由查询结果获取的值。
数据库服务器已经调整到良好状态(~12GB 缓冲区-space 等)
好吧,为了加快查询速度,我决定在 LogTime
字段上对 table 进行分区。我通过用 PARTITION BY RANGE
划分 table 来实现这个目标。现在我有 365 个分区用于 table(1 个分区 1 天,每个分区有 500 万条记录)。
问题是我们对查询性能不满意,我一直在寻找一种方法将分区分解成更小的部分..假设在 LogTime 和 RegionID 上分区 a table .. .我不确定它是否适用于子分区...
对于
select b.CityName, a.val1, a.val2
from DataRepo a
left join City b on a.CityID = b.CityID
where (a.LogTime >= '2015-08-01 00:00:00'
and a.LogTime <= '2015-08-05 00:00:00' )
and a.RegionID = 1
and a.ProvinceID = 14;
最优指标为
INDEX(RegionID, ProvinceID, -- in either order
LogTime) -- last
否 PARTITIONing
将有助于加快查询速度,超过该索引可以提供的速度。
(无关)
你是故意要查4天加一秒的吗?
我喜欢这个设计模式:
where (a.LogTime >= '2015-08-01'
and a.LogTime < '2015-08-01' + INTERVAL 4 DAY )
哦...这个索引会更快,因为它是 "covering":
INDEX(RegionID, ProvinceID, -- in either order
LogTime, -- range
CityID) -- the rest of the fields used in the SELECT
这样,查询将完全在索引中执行(JOIN
除外),而不会触及数据。 EXPLAIN
会说 "Using index".
(另说)Region是Province的子集吗?或相反亦然?如果是这样,您不需要 Fact table 中的两列,对吗? (缩小事实 table 是另一种提高性能的技术,因为你无疑是 I/O-bound。)
(更多)是省份INT
?那是4个字节。如果省份不足255个,就用TINYINT UNSIGNED
,只有1个字节。这将在 table 中节省将近 1GB,另外在我建议的索引中节省 1GB。
我有一个 table,里面有大约 3 亿条记录(仅 60 天)。 table 结构非常简单..
它有 12 列,其中 4 列是索引的:
LogTime - DateTime
RegionID - Integer
ProvinceID - Integer
CityID - Integer
还有一个唯一索引:
UNIQUE INDEX UI_IDX (`LogTime`, `RegionID`, `ProvinceID`, `CityID`);
其余字段只是主要由查询结果获取的值。
数据库服务器已经调整到良好状态(~12GB 缓冲区-space 等)
好吧,为了加快查询速度,我决定在 LogTime
字段上对 table 进行分区。我通过用 PARTITION BY RANGE
划分 table 来实现这个目标。现在我有 365 个分区用于 table(1 个分区 1 天,每个分区有 500 万条记录)。
问题是我们对查询性能不满意,我一直在寻找一种方法将分区分解成更小的部分..假设在 LogTime 和 RegionID 上分区 a table .. .我不确定它是否适用于子分区...
对于
select b.CityName, a.val1, a.val2
from DataRepo a
left join City b on a.CityID = b.CityID
where (a.LogTime >= '2015-08-01 00:00:00'
and a.LogTime <= '2015-08-05 00:00:00' )
and a.RegionID = 1
and a.ProvinceID = 14;
最优指标为
INDEX(RegionID, ProvinceID, -- in either order
LogTime) -- last
否 PARTITIONing
将有助于加快查询速度,超过该索引可以提供的速度。
(无关) 你是故意要查4天加一秒的吗?
我喜欢这个设计模式:
where (a.LogTime >= '2015-08-01'
and a.LogTime < '2015-08-01' + INTERVAL 4 DAY )
哦...这个索引会更快,因为它是 "covering":
INDEX(RegionID, ProvinceID, -- in either order
LogTime, -- range
CityID) -- the rest of the fields used in the SELECT
这样,查询将完全在索引中执行(JOIN
除外),而不会触及数据。 EXPLAIN
会说 "Using index".
(另说)Region是Province的子集吗?或相反亦然?如果是这样,您不需要 Fact table 中的两列,对吗? (缩小事实 table 是另一种提高性能的技术,因为你无疑是 I/O-bound。)
(更多)是省份INT
?那是4个字节。如果省份不足255个,就用TINYINT UNSIGNED
,只有1个字节。这将在 table 中节省将近 1GB,另外在我建议的索引中节省 1GB。