分区是否有助于按主键查找和插入/更新?

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个问题:

  1. 在我看来,通过 PK 返回 1 行 ( SELECT x, y FROM table WHERE pk = 123) 的简单选择在性能上与分区没有实际差异。那正确吗?

  2. 加入或选择为WHERE PK IN(SELECT PK FROM ...)怎么样?与单个表相比,它会导致更多的扫描加入分区表吗?

  3. 考虑到我通常使用以下方法进行大量并发批处理(多个服务器可能同时发送数据):

    • INSERT INTO X VALUES (1, 'A'), (2, 'B'), ... ON DUPLICATE KEY UPDATE ... 或者

    • REPLACE INTO X VALUES(1, 'A'), (2, 'B'),...

分区是否有助于并发插入和更新,比如能够同时影响多个分区?

提前致谢。

Ric*_*mes 1

你的问题

Q1:如果 PK 是分区键,则分区键上的“点查询”( WHERE PK = constant) 将进行“修剪”,然后(希望)使用它找到的单个分区中的索引。与具有合适索引的简单表相比,没有任何改进。
Q1:如果 PK 是PRIMARY KEY,但不是分区键,则查询必须打开并在每个分区中查找以查找该行,因此速度较慢。

Q2:通常IN ( SELECT ... )表现不佳,在某些情况下非常糟糕,应该避免。使用 aJOIN代替。对于分区,可能不会使用“修剪”。因此缓慢。

Q3: INSERT无论如何,速度可能大致相同。由于复杂性较低,普通表可能会更快。
Q3: REPLACEDELETE+ 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/更新/等操作。