繁体   English   中英

性能:使用索引和分区(PostgreSQL)

[英]Performance: Using indexing and partitioning (PostgreSQL)

我有一个相当简单的数据库模型。 我的表“main”看起来像这样:

| id (PK) | device_id (int) | msg_type (int) | rawdata (text) | timestamp (date+time) |

因此,每个收到的消息都存储在该表中,包括消息类型,时间戳,发送它的设备和rawdata。

另外,对于每个可能的msg_type(总共约30个),我有一个单独的表存储解析的原始数据。 表“main_type1”的示例:

| id (PK) | main_id (FK) | device_id (int) | attribute_1 | attribute_2 | attribute_n |

(每个msg_type的结构不同,并且消息不是均匀分布的,这意味着某些表有些表很小)。

请注意,device_id始终包含在rawdata中,因此每个表都有此列。

现在我的问题:

我曾经有过如下问题的查询:

select attribute_1, attribute_2 from main_type1 inner join main on main_type1.main_id = main.id where timestamp > X and timestamp < Y and main.device_id = Z

一开始一切都足够快,也很快。 但现在我的数据库在“main”中有超过400.000.000个条目。 查询现在需要15分钟。

索引

我试图使用索引,如:

CREATE INDEX device_id_index ON main (device_id);

好吧,现在我可以从主表中更快地检索数据,但它对联接没有帮助。 我最大的问题是我只将时间戳信息存储在主表中。 所以我必须一直加入......这是我的数据库模型的一般失败吗? 我试图避免两次存储时间戳。

分区

一种解决方案是使用分区为每个device_id创建一个包含rawdata的新表吗? 然后我(当然会自动)创建适当的分区,例如:

main_device_id_343223
main_device_id_4563
main_device_id_92338
main_device_id_4142315

这会给我带来与连接相关的速度优势吗? 我还有其他选择吗? 为了完整起见:我正在使用PostgreSQL

由于您的问题是执行join的时间,因此首先要尝试通过以下方式创建索引来加速查询:

  1. 帮助连接本身的索引,在这种情况下是main.id中外键main.idmain_type1 (请注意,外键声明不会自动创建索引):

     CREATE INDEX main_type_main_id_index ON main_type1(main_id); 
  2. 有助于限制查询所考虑的数据集的索引,在本例中为timestamp属性:

     CREATE INDEX main_timestamp_index ON main(timestamp); 

如果查询仅查找值的特定子集,您还可以考虑为属性时间戳创建部分索引的可能性。

如果这些索引不能以显着的方式加速查询,那么您应该遵循@klin的答案。

我建议这个场景:首先,创建Renzo提出的索引。 如果这不能提高性能,请尝试使用分区。

从文档:

分区可以提供多种好处:在某些情况下可以显着提高查询性能,尤其是当表的大多数访问量很大的行位于单个分区或少量分区中时。 分区替代了索引的前导列,减少了索引大小,使得索引的大量使用部分更有可能适合内存。 (......)

如果使用分区,则包含对特定设备的引用的所有查询(例如在您的问题中)将会快得多。 只有那些将应用于许多device_id的查询(例如,包含聚合)可能会更慢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM