[英]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
的时间,因此首先要尝试通过以下方式创建索引来加速查询:
帮助连接本身的索引,在这种情况下是main.id
中外键main.id
的main_type1
(请注意,外键声明不会自动创建索引):
CREATE INDEX main_type_main_id_index ON main_type1(main_id);
有助于限制查询所考虑的数据集的索引,在本例中为timestamp属性:
CREATE INDEX main_timestamp_index ON main(timestamp);
如果查询仅查找值的特定子集,您还可以考虑为属性时间戳创建部分索引的可能性。
如果这些索引不能以显着的方式加速查询,那么您应该遵循@klin的答案。
我建议这个场景:首先,创建Renzo提出的索引。 如果这不能提高性能,请尝试使用分区。
分区可以提供多种好处:在某些情况下可以显着提高查询性能,尤其是当表的大多数访问量很大的行位于单个分区或少量分区中时。 分区替代了索引的前导列,减少了索引大小,使得索引的大量使用部分更有可能适合内存。 (......)
如果使用分区,则包含对特定设备的引用的所有查询(例如在您的问题中)将会快得多。 只有那些将应用于许多device_id的查询(例如,包含聚合)可能会更慢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.