mariadb (mysql) 子分区错误(总子分区数超过 64)

mariadb (mysql) sub partition error (total sub partition count exceeds 64)

enter image description here

你好

我想配置一个分区(每月)/子分区(每天)作为上面的查询。 如果子分区总数超过64, '(errno:168“来自引擎的未知(一般)错误”)' 由于错误,未创建 table。 (创建小于64成功)

我知道可以创建的最大分区数(包括子分区)是 8,192,有什么我遗漏的吗?

下面是日志table。

create table detection_log
(
    id bigint auto_increment,
    detected_time datetime default  '1970-01-01' not null,
    malware_title varchar(255) null,
    malware_category varchar(30) null,
    user_name varchar(30) null,
    department_path varchar(255) null,
    PRIMARY KEY (detected_time, id),
    INDEX `detection_log_id_uindex` (id),
    INDEX `detection_log_malware_title_index` (malware_title),
    INDEX `detection_log_malware_category_index` (malware_category),
    INDEX `detection_log_user_name_index` (user_name),
    INDEX `detection_log_department_path_index` (departmen`enter code here`t_path)
);
  • SUBPARTITIONs 没有提供我所知道的好处。
  • HASH 分区要么没有好处,要么损害性能。

所以...解释一下您希望通过分区获得什么;然后我们可以讨论 any 类型的分区是否值得做。另外,提供可能的 SELECTs,以便我们讨论最优的 INDEXes。如果您需要“二维”索引,可能 表示需要分区(但仍然不是子分区)。

更多

我明白了PRIMARY KEY(detected_time,id)。这提供了一种非常快速的方法

SELECT ...
    WHERE detected_time BETWEEN ... AND ...
    ORDER BY  detected_time, id

事实上,它可能 比您也对 table 进行分区要快 。 (作为一般规则,在PK的第一部分进行分区是没有用的。)

如果需要的话

SELECT ...
    WHERE user_id = 123
      AND detected_time BETWEEN ... AND ...
    ORDER BY  detected_time, id

那么这是最优的:

INDEX(user_id, detected_time, id)

同样,可能比任何列上的任何形式的分区都快。

与 1000 行 table 相比,“点查询”(WHERE key = 123) 在 10 亿行 table 中多花费几毫秒。差异很少是重要的。 BTree 的深度(可能是 5 层 vs 2 层)是主要区别。如果你 PARTITION table,你可能会删除 BTree 的 1 或 2 层,但用代码替换它们以“修剪”到所需的分区。我声称这种权衡不会提供性能优势。

无论 table 大小如何,“范围查询”的速度几乎相同。这是因为该结构实际​​上是一个B+Tree,所以获取'next'行是非常高效的。

因此,在巨大 table上优化查询的主要目标是利用B+Tree的特性。

分页

SELECT  log.detected_time, log.user_name, log.department_path,
        log.malware_category, log.malware_title
    FROM  detection_log as log
    JOIN  
    (
        SELECT  id
            FROM  detection_log
            WHERE  user_name = 'param'
            ORDER BY  detected_time DESC
            LIMIT  25 OFFSET 1000 
    ) as temp  ON temp.id = log.id;

好的部分:查找 ID,然后获取数据。

慢的部分:使用OFFSET

有这个复合索引:INDEX(user_name, detected_time, id)顺序。使用 department_path.

时创建另一个索引

而不是 OFFSET,“记住你离开的地方”。专门关于此的博客:http://mysql.rjweb.org/doc.php/pagination

正在清除

一年后删除是 PARTITIONing 的绝妙用法。使用 PARTITION BY RANGE(TO_DAYS(detected_time)) 并有 ~55 个每周或 15 个每月的分区。有关详细信息,请参阅 HTTP://mysql.rjweb.org/doc.php/partitionmaint。 DROP PARTITIONDELETE 快得多。 (这个分区不会加速SELECT。)