MariaDB -提高超过1亿数据表性能的策略

cdmah0mi  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(578)

我有一个存储用户数据的表,它目前有超过1亿条数据。
由于这个表有大量的数据,涉及日期范围的查询非常慢。例如,在这个表中,有一个日期类型的出生列,我们在其中做了很多事情,如示例所示:

SELECT * FROM USERS WHERE YEAR(CURDATE() - YEAR(birth) > 15

为了提高这些查询的性能,我考虑将该表按年份划分为93个分区。
我考虑过分区,例如,像这样的列表:

ALTER TABLE USERS
PARTITION BY range(year(birth))(
PARITTION p_year_1930 VALUES LESS THAN (1930),
PARITTION p_year_1931 VALUES LESS THAN (1931),
...
PARITTION p_year_1930 VALUES LESS THAN (2023),
)

使用hash:

PARTITION BY hash(year(birth))(
partitions 93
)

我的问题是,在这种情况下,分区是否是一个好的策略,或者是否有另一个更好的解决方案,例如使用索引键,以及在这种情况下使用hash或range在性能方面是否存在差异,考虑使用这个where子句的查询:YEAR(CURDATE()) - YEAR(birth) > 15
@编辑
根据@Schwern的要求,我的表的结构:

client_inss_dados | CREATE TABLE `client_inss_dados` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `SSN` varchar(50) DEFAULT NULL,
  `NAME` varchar(255) DEFAULT NULL,
  `SEX` varchar(255) DEFAULT NULL,
  `BIRTH` varchar(255) DEFAULT NULL,
  `WAGE` varchar(255) DEFAULT NULL,
  `COD_BANK` varchar(255) DEFAULT NULL,
  `ADDRESS` varchar(255) DEFAULT NULL,
  `CITY` varchar(255) DEFAULT NULL,
  `PHONE_01` varchar(255) DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
  PRIMARY KEY (`ID`) USING BTREE,
  KEY `idx_SSN` (`SSN`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci

SELECT VERSION();
10.5.19-MariaDB

sqougxex

sqougxex1#

正如@Schwern所指出的,创建一个出生年份的列,可以是generated column

ALTER TABLE client_inss_dados
ADD yr INT GENERATED ALWAYS AS (YEAR(birth)) STORED,
ADD INDEX yr_index (yr)

使用索引的一般原则是它是一个暴露的值,而不是SQL中的表达式。所以:

SELECT * FROM USERS WHERE yr < YEAR(CURDATE()) - 15

使用EXPLAIN {query}查看是否使用了索引yr_index
MariaDB-11.1 preview刚刚推出了一些功能来简化应用于列的YEAR函数,以便在date/datetime/timestamp列上使用索引。
因此,第一步是将BIRTH存储为date类型,并在其上创建索引:

ALTER TABLE client_inss_dados
MODIFY BIRTH date
, ADD INDEX (BIRTH)

fiddle所示,正确日期格式的BIRTH将被转换。
使用MariaDB-11.1预览功能,只需要对查询进行一个小的重新排列(MariaDB中没有实现对数学表达式/关系进行复杂的重新排列以匹配索引)。

SELECT * FROM client_inss_dados WHERE YEAR(BIRTH) < YEAR(CURDATE()) - 15

如果在预览阶段没有发现此实现的主要问题,未来的11.1和更高版本将具有此功能。在11.1预览结束后检查MDEV-8320的固定版本以检查是否包含此功能。

相关问题