ale*_*tos 28 sql postgresql performance postgresql-performance
我在Postgres数据库的SELECT查询中遇到速度问题.
我有一个表有两个整数列作为键:(int1,int2)这个表有大约7000万行.
我需要在这种环境中进行两种简单的SELECT查询:
SELECT * FROM table WHERE int1=X;
SELECT * FROM table WHERE int2=X;
Run Code Online (Sandbox Code Playgroud)
这两个选择在这7000万个中返回大约10,000行.为了尽可能快地工作,我考虑使用两个HASH索引,每列一个.不幸的是结果并不那么好:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on lec_sim (cost=232.21..25054.38 rows=6565 width=36) (actual time=14.759..23339.545 rows=7871 loops=1)
Recheck Cond: (lec2_id = 11782)
-> Bitmap Index Scan on lec_sim_lec2_hash_ind (cost=0.00..230.56 rows=6565 width=0) (actual time=13.495..13.495 rows=7871 loops=1)
Index Cond: (lec2_id = 11782)
Total runtime: 23342.534 ms
(5 rows)
Run Code Online (Sandbox Code Playgroud)
这是其中一个查询的EXPLAIN ANALYZE示例.这需要大约23秒.我的期望是在不到一秒的时间内获得这些信息.
这些是postgres db config的一些参数:
work_mem = 128MB
shared_buffers = 2GB
maintenance_work_mem = 512MB
fsync = off
synchronous_commit = off
effective_cache_size = 4GB
Run Code Online (Sandbox Code Playgroud)
任何帮助,评论或想法都会非常感激.
先感谢您.
wil*_*ynn 34
将我的评论提取到答案中:这里的索引查找速度非常快 - 所有时间都花在检索实际行上.23秒/ 7871行=每行2.9毫秒,这对于检索分散在磁盘子系统中的数据是合理的.寻求缓慢; 你可以a)使你的数据集适合RAM,b)购买SSD,或c)提前组织你的数据,以尽量减少搜索.
PostgreSQL 9.2有一个称为仅索引扫描的功能,允许它(通常)在不访问表的情况下回答查询.您可以将此与btree自动维护顺序的索引属性结合使用,以快速进行此查询.你提到int1,int2和两个花车:
CREATE INDEX sometable_int1_floats_key ON sometable (int1, float1, float2);
CREATE INDEX sometable_int2_floats_key ON sometable (int2, float1, float2);
SELECT float1,float2 FROM sometable WHERE int1=<value>; -- uses int1 index
SELECT float1,float2 FROM sometable WHERE int2=<value>; -- uses int2 index
Run Code Online (Sandbox Code Playgroud)
另请注意,这不会神奇地擦除磁盘搜索,只是将它们从查询时间移动到插入时间.它也会占用您的存储空间,因为您正在复制数据.不过,这可能是你想要的权衡.
ale*_*tos 20
谢谢你willglyn.正如你所注意到的那样,问题在于通过高清搜索而不是查找索引.您提出了许多解决方案,例如在RAM中加载数据集或购买SSD HD.但是忘记了这两个涉及管理数据库本身之外的事情,你提出了两个想法:
由于我在PostgreSQL 9.1服务器下,我决定选择"1".
我制作了一份表格.所以现在我有两次相同数据的同一个表.我为每一个创建了一个索引,第一个索引由(int1)索引,第二个索引由(int2)索引.然后我将它们(CLUSTER表USING ind_intX)按其各自的索引聚类.
我现在发布了一个相同查询的EXPLAIN ANALYZE,在其中一个聚簇表中完成:
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using lec_sim_lec2id_ind on lec_sim_lec2id (cost=0.00..21626.82 rows=6604 width=36) (actual time=0.051..1.500 rows=8119 loops=1)
Index Cond: (lec2_id = 12300) Total runtime:
1.822 ms (3 rows)
现在寻求的速度非常快.我从23秒下降到~2毫秒,这是一个令人印象深刻的改进.我认为这个问题已经解决了,我希望这对于遇到同样问题的其他人也有用.
非常感谢willglynn.