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。