You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MariaDB分区表未按partition条件执行筛选问题排查

问题描述

我在Laravel应用里采用了这样的范式:编辑实体时不修改原数据库记录,而是生成新的实体副本。每个可编辑实体都关联change_metadata_partitioned表的一条记录,其中obsolete字段值为1时代表对应实体的旧版本。

为了优化查询obsolete=0有效数据的场景,我给该表按obsolete字段创建了LIST分区,表结构如下:

Create Table: CREATE TABLE `change_metadata_partitioned` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `table_name` varchar(255) NOT NULL,
  `changeable_id` bigint(20) unsigned NOT NULL,
  `created_by` bigint(20) unsigned DEFAULT NULL,
  `deleted` int(11) NOT NULL DEFAULT 0,
  `confirmed_at` datetime DEFAULT NULL,
  `confirmed_by` bigint(20) unsigned DEFAULT NULL,
  `rejected_at` varchar(255) DEFAULT NULL,
  `rejected_by` bigint(20) unsigned DEFAULT NULL,
  `deleted_by` bigint(20) unsigned DEFAULT NULL,
  `obsolete` int(11) NOT NULL DEFAULT 0,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`,`obsolete`)
) ENGINE=InnoDB AUTO_INCREMENT=5483 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
 PARTITION BY LIST (`obsolete`)
(PARTITION `dObsolete` VALUES IN (1) ENGINE = InnoDB,
 PARTITION `dNotObsolete` VALUES IN (0) ENGINE = InnoDB)

按预期,带WHERE obsolete=?条件的查询应该只扫描对应分区,但执行EXPLAIN SELECT * FROM change_metadata_partitioned WHERE obsolete=1时,结果显示是全表扫描:

id: 1
  select_type: SIMPLE
        table: change_metadata_partitioned
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1765
        Extra: Using where

使用的MariaDB版本是:Ver 15.1 Distrib 10.4.28-MariaDB, for Win64 (AMD64)

问题原因分析

导致分区修剪未生效、出现全表扫描的常见原因有以下几点:

  • 统计信息过时
    数据库优化器依赖表的统计信息判断执行计划,如果change_metadata_partitioned表的统计信息未及时更新,优化器可能无法识别分区键的分布情况,从而选择全表扫描而非分区修剪。可执行ANALYZE TABLE change_metadata_partitioned;更新统计信息后,重新执行EXPLAIN查看结果。
  • MariaDB版本的分区修剪特性限制
    在10.4.x版本的MariaDB中,LIST分区的修剪逻辑可能存在场景识别问题,尤其是当分区键作为复合主键的一部分时,优化器可能无法正确解析查询条件与分区的关联。可尝试升级到10.5及以上版本验证是否为版本bug导致。
  • 查询条件的隐式类型转换
    虽然obsolete字段是int类型,但如果查询时条件值存在隐式类型转换(比如传入字符串类型的"1"而非整数1),优化器可能无法匹配分区规则。当前直接写obsolete=1的情况可排除,但如果是应用参数绑定传入值,需要确认参数类型是否匹配。
  • 复合主键顺序的潜在影响
    虽然已将obsolete包含在主键中(符合InnoDB分区表要求),但复合主键的顺序可能影响优化器判断,不过这个因素导致失效的概率较低,可作为最后排查项。

内容的提问来源于stack exchange,提问作者Abw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 23:03:25