当前位置: 首页 > 知识库问答 >
问题:

MariaDB / MySQL:具有一个值列的表的索引结构

全兴运
2023-03-14

我有一个包含三列的玛丽亚DB 我的表:

`time` int not null, 
`sensor` tinyint not null, 
`value` decimal (6,4) not null

此外,我有一个关于列时间和传感器的主键(BTREE)

该表有2.5亿行,每10秒添加20条新记录。表上的所有SELECTS都有一个WHERE子句,要么仅在time上,要么在time传感器上。

这在性能方面效果很好,但索引使用的磁盘空间甚至比表本身还要多(数据为2.2GB,索引为2.7GB)。这对我来说似乎有点傻,因为索引基本上是整个表,这意味着MariaDB基本上将所有数据翻了一番。

这张桌子有更好的结构吗?

共有1个答案

祁高格
2023-03-14

数据库索引的整个要点是以空间换取时间。是的,索引占用的空间与表大致相同,这是正常的,尤其是当表像您这样有短行时。

如果您切换到InnoDB存储引擎,您的主键将变成所谓的聚集索引。也就是说,整个表将包含在主键的索引中。这样可以节省大量的磁盘空间。

您应该切换到InnoDB: MyISAM是一个遗留的存储引擎,没有得到MariaDB开发人员的太多关注。如果由于某种原因InnoDB不适合您,请切换到更现代的Aria存储引擎。它类似于MyISAM。和MyISAM一样,它不使用聚集的PK索引。

请注意:您的主键在< code >(时间,传感器)上。这意味着它最适合如下所示的where子句:

 WHERE time BETWEEN start AND finish

如果您重新制作了主键,使其位于(传感器,时间)上,则适合

 WHERE sensor=somesensor AND time BETWEEN start AND finish

为什么?MySQL随机访问BTREE索引中第一个符合条件的行,然后依次扫描到最后一个符合条件的行。你可以在这里和这里阅读关于多列索引的内容。

因此,您对主键列顺序的选择应该基于这两个< code>WHERE模式中的哪一个对性能更关键:仅时间范围还是传感器和时间范围。

如果这是我的表格,我会这样定义:

CREATE TABLE series (
    time TIMESTAMP NOT NULL DEFAULT current_timestamp(),
    sensor SMALLINT(6) NOT NULL DEFAULT '0',
    value DECIMAL(6,4) NOT NULL DEFAULT '0.0000',
    PRIMARY KEY (sensor, time) USING BTREE,
    INDEX time_covering (time, sensor, value) USING BTREE
) COLLATE='utf8mb4_general_ci' ENGINE=InnoDB;

该表定义提供了一个聚类主键,该主键针对先按传感器再按时间范围进行过滤进行了优化。我还添加了一个覆盖索引(基本上是表的副本),只针对按时间范围过滤进行了优化。有关覆盖索引的信息,请参见本文的最后一节。

它使用< code>TIMESTAMP数据类型。它们在表示时间上和整数一样有效,你可以从时间算法中获益。这将为您提供传感器3昨天的读数。

WHERE time >= CURDATE() - INTERVAL 1 DAY
  AND time < CURDATE()
  AND sensor = 3

它使用一个小号而不是一个TINYINT作为传感器编号。您不太可能用完传感器编号,并且 TINYINT 数据仅在每行中有多个传感器编号时才有助于节省空间。

 类似资料:
  • 问题内容: 我面临以下问题,我不确定什么是最佳实践。 考虑下表(该表会变大): id PK | Giver_id FK | FK | 日期 我正在使用InnoDB,据我了解,它会自动为两个外键列创建索引。但是,我还将在需要匹配以下特定组合的情况下进行大量查询: 。 每个这样的组合在表中将是唯一的。 在这些列上添加双列索引有什么好处,还是理论上两个单独的索引足够/相同? 问题答案: 如果您有两个单列

  • 我讨论这个问题已经有一段时间了,但没有结果。这几乎是一个重复的问题,至少有一个其他的问题在这里,但我不能完全弄清楚如何做,确切地说,我正在寻找从网上相关的答案。 我有一个熊猫数据帧(我们称之为),看起来像: 其中是索引。我想将其转换为类似以下内容: 因此,基本上,每个对应于相同索引的都应该组合到一个列表(或一个集合,或一个元组)中,该列表成为对应索引的。并且,如图所示,在相似的索引行之间是相同的,

  • 问题内容: 我需要一个表来存储一些评分,在此表中,我有一个 综合索引(user_id,post_id) 和其他列来标识不同的评分系统。 在此表中,我没有 主键, 因为 主键 必须是唯一的,而INDEX不必是唯一的,就我而言,唯一性是一个问题。 例如我可以有 缺少PRIMARY KEY可能会导致性能问题?我的表结构好还是需要更改? 谢谢 问题答案: 几点: 听起来您只是在使用表的当前唯一特性,并将其

  • 我创建了一个带有主键(UsersID、AccountsID)的帐户/用户表,如下所示。我是否应该为Users表添加索引?

  • 问题内容: 我说有Python清单。我也有一个索引列表,例如。如何获取带有索引的元素的列表? 问题答案: 您可以使用 列表推导 来获取该列表: 这等效于: 输出: 注意: 请记住,这是用于访问特定索引中a元素的表示法。