Nat*_*tan 5 mysql mariadb partitioning database-internals
我使用的是 MariaDB 10.1 和默认的 InnoDB 存储,我有几个表,目前有 10 到 1 亿行。这些表将保持每月数百万的增长,而且主要是缓存。
它们要么有一个单列主键 ( BIGINT
) 或一个复合主键(两BIGINT
列),没有 AUTO_INCREMENT,我总是按主键插入、选择或更新。我还通过主键或 selects 进行了很多连接WHERE PK IN (1, 2, 3, 4...)
。
此外,这些表每小时会收到大量更新,我通常一次以 5000 或 10000 个批次更新它们。对于其中一些表,我们有比选择更多的插入和更新。
我有3个问题:
在我看来,通过 PK 返回 1 行 ( SELECT x, y FROM table WHERE pk = 123
) 的简单选择在性能上与分区没有实际差异。那正确吗?
加入或选择为WHERE PK IN(SELECT PK FROM ...)
怎么样?与单个表相比,它会导致更多的扫描加入分区表吗?
考虑到我通常使用以下方法进行大量并发批处理(多个服务器可能同时发送数据):
INSERT INTO X VALUES (1, 'A'), (2, 'B'), ... ON DUPLICATE KEY UPDATE ...
或者
REPLACE INTO X VALUES(1, 'A'), (2, 'B'),...
分区是否有助于并发插入和更新,比如能够同时影响多个分区?
提前致谢。
你的问题
Q1:如果 PK 是分区键,则分区键上的“点查询”( WHERE PK = constant
) 将进行“修剪”,然后(希望)使用它找到的单个分区中的索引。与具有合适索引的简单表相比,没有任何改进。
Q1:如果 PK 是PRIMARY KEY
,但不是分区键,则查询必须打开并在每个分区中查找以查找该行,因此速度较慢。
Q2:通常IN ( SELECT ... )
表现不佳,在某些情况下非常糟糕,应该避免。使用 aJOIN
代替。对于分区,可能不会使用“修剪”。因此缓慢。
Q3: INSERT
无论如何,速度可能大致相同。由于复杂性较低,普通表可能会更快。
Q3: REPLACE
是DELETE
+ INSERT
。 通常INSERT ... ON DUPLICATE KEY UPDATE ...
是一个更好的结构;看看是否适用。但是,同样,性能没有提高。
在
WHERE PK IN (1, 2, 3, 4...)
-- 我想我听说如果列表很“短”,它将使用分区修剪。或者,如果列表很长,则跳过修剪。无论哪种情况,带有 PK 索引的简单表至少会一样快。
修剪
以这种方式考虑修剪:首先它必须找到分区(其作用非常类似于“子表”),然后它必须使用索引(如果可用)向下钻取到所需的行。不进行分区,则跳过剪枝步骤;但BTree索引稍深一些。所以这是一个权衡。
注意:这通常意味着分区表和等效的非分区表的最佳索引集是不同的。
案例3
“表的索引太大而无法缓存,但一个分区的索引是可缓存的”这一警告似乎不适用于您的情况。情况 3 来自一个时间序列,其中大部分活动都在最新分区(和PARTITION BY RANGE(TO_DAYS(...))
)中,并且该分区适合 buffer_pool,但整个表不适合。
(也就是说,关于案例 3 的相关性,我同意 Natan,而不是 Jarwad。)
通过哈希
BY HASH
- 没有用。(来自链接:“按范围分区是唯一有用的方法。”)(或者至少,我还没有看到哈希的用例可以提高性能。)
食入
“每月增长几百万”这并不是很快。“每天增长几百万”将开始具有挑战性,此时我会向您指出我的高速摄取博客。即便如此,您可能会从那里得到一个提示——将更改加载到临时表中,然后从它到“真实”表执行插入/替换/iodku/更新/等操作。