【问题标题】:MySQL - clarification on table partition / subpartitionMySQL - 表分区/子分区的说明
【发布时间】:2015-09-14 07:19:19
【问题描述】:

我有一张表,其中包含大约 3 亿条记录(仅 60 天)。表结构很简单..
它有 12 列,其中 4 列已编入索引:

LogTime - DateTime
RegionID - Integer
ProvinceID - Integer
CityID - Integer

还有一个唯一索引:

UNIQUE INDEX UI_IDX (`LogTime`, `RegionID`, `ProvinceID`, `CityID`); 

其余字段只是主要由查询结果获取的值。

数据库服务器已经调好,状况良好(~12GB 用于缓冲空间等)

好吧,为了加快查询速度,我决定在LogTime 字段上对表进行分区。我通过使用PARTITION BY RANGE 对表进行分区来实现这个目标。现在我的表有 365 个分区(1 个分区 1 天,每个分区 500 万条记录)。

问题是我们对查询性能不满意,我一直在寻找一种方法将分区分解为更小的部分.. 假设在 LogTime 和 RegionID 上对表进行分区...我不确定如果它适用于子分区...

【问题讨论】:

  • 分区本质上不提供任何性能。请向我们展示您需要更好性能的实际查询。索引和分区必须基于查询。
  • 不要使用超过50个左右的分区;事情变慢了。更多关于分区:mysql.rjweb.org/doc.php/partitionmaint
  • 嗨瑞克,感谢您的回复。这是我的示例查询之一,需要几分钟才能反馈结果: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;

标签: mysql database innodb database-partitioning


【解决方案1】:

对于

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天加1秒是故意要查的吗?

我喜欢这种设计模式:

    where  (a.LogTime >= '2015-08-01'
       and  a.LogTime <  '2015-08-01' + INTERVAL 4 DAY )

哦...这个索引会更快,因为它是“覆盖”:

INDEX(RegionID, ProvinceID, -- in either order
      LogTime,    -- range
      CityID)     -- the rest of the fields used in the SELECT

这样,查询将在索引中完全执行(除了JOIN),而不涉及数据。 EXPLAIN 会说“使用索引”。

(另一边)地区是省的子集吗?或相反亦然?如果是这样,您不需要 Fact 表中的两列,对吗? (缩小 Fact 表是另一种提高性能的技术,因为您无疑是 I/O 绑定的。)

(更多) 省INT?那是4个字节。如果有 255 个省以下,则使用TINYINT UNSIGNED,它只有 1 个字节。这将在表中节省近 1GB,再加上我建议的索引中的另一个 GB。

【讨论】:

  • 我现在可以确认的一件事是,您使用 TINYINT 而不是 INT 可能是正确的,我会处理的。我对您提出的最佳索引有一个问题..正如您在我的第一篇文章中看到的那样,我已经为相同的字段定义了 UNIQUE INDEX ..我认为那里没有区别..您能解释一下这里的区别吗?谢谢。
  • 您的UNIQUE 密钥LogTime 开头。最后一个有用的列是范围列。那就是您将在 LogTime 上过滤 only,必须扫描大量行才能过滤省份和地区。我的索引使用了所有 3 列。你的可以通过重新排列变成我的。
  • 我想看整个SHOW CREATE TABLE;可能还有其他需要批评的东西。对于 300M 行,很多细节变得非常重要。 (有 300 行,细节无关紧要。)
  • 知道了 :) 非常感谢您的宝贵时间。允许我根据您的回复修改必填字段/索引。稍后我会和你一起检查结果。 ps:现在是凌晨 4 点 ;)
  • 印度? ALTER 需要很长时间,同时进行所有更改。并考虑使用pt-online-schema-change
猜你喜欢
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多