【发布时间】:2014-01-07 15:42:08
【问题描述】:
我一直在尝试在 Windows Server 2012 上的 Azure VM 上运行 postgres 9.3。我最初是在 7GB 的服务器上运行它...我现在在 14GB 的 Azure VM 上运行它。在尝试解决下面描述的问题时,我增加了一个尺寸。
顺便说一下,我对 posgresql 还是很陌生,所以我只是一点一点地了解配置选项。此外,虽然我很想在 Linux 上运行它,但我和我的同事根本没有专业知识来解决 Linux 出现问题时出现的问题,因此 Windows 是我们唯一的选择。
问题描述:
我有一个名为 test_table 的表;它目前存储了大约 9000 万行。它将每月增长约 3-4 百万行。 test_table 中有 2 列:
id (bigserial)
url (charachter varying 300)
我在从几个 CSV 文件导入数据后创建了索引。两列都被索引.... id 是主键。 url 上的索引是通过 pgAdmin 使用默认值创建的普通 btree。
我跑的时候:
SELECT sum(((relpages*8)/1024)) as MB FROM pg_class WHERE reltype=0;
...总大小为5980MB
这里有问题的2个索引的单独大小如下,我通过运行得到它们:
# SELECT relname, ((relpages*8)/1024) as MB, reltype FROM pg_class WHERE
reltype=0 ORDER BY relpages DESC LIMIT 10;
relname | mb | reltype
----------------------------------+------+--------
test_url_idx | 3684 | 0
test_pk | 2161 | 0
其他较小的表上还有其他索引,但它们很小(
使用 url 查询 test_table 时,特别是在搜索中使用通配符时,问题在于速度(或缺少通配符)。例如
select * from test_table where url like 'orange%' limit 20;
...运行需要 20-40 秒。
在上面运行解释分析得到以下结果:
# explain analyze select * from test_table where
url like 'orange%' limit 20;
QUERY PLAN
-----------------------------------------------------------------
Limit (cost=0.00..4787.96 rows=20 width=57)
(actual time=0.304..1898.583 rows=20 loops=1)
-> Seq Scan on test_table (cost=0.00..2303247.60 rows=9621 width=57)
(actual time=0.302..1898
.542 rows=20 loops=1)
Filter: ((url)::text ~~ 'orange%'::text)
Rows Removed by Filter: 210286
Total runtime: 1898.650 ms
(5 rows)
再举一个例子……这次是美国和.com之间的通配符……
# explain select * from test_table where url
like 'american%.com' limit 50;
QUERY PLAN
-------------------------------------------------------
Limit (cost=0.00..11969.90 rows=50 width=57)
-> Seq Scan on test_table (cost=0.00..2303247.60 rows=9621 width=57)
Filter: ((url)::text ~~ 'american%.com'::text)
(3 rows)
# explain analyze select * from test_table where url
like 'american%.com' limit 50;
QUERY PLAN
-----------------------------------------------------
Limit (cost=0.00..11969.90 rows=50 width=57)
(actual time=83.470..3035.696 rows=50 loops=1)
-> Seq Scan on test_table (cost=0.00..2303247.60 rows=9621 width=57)
(actual time=83.467..303
5.614 rows=50 loops=1)
Filter: ((url)::text ~~ 'american%.com'::text)
Rows Removed by Filter: 276142
Total runtime: 3035.774 ms
(5 rows)
然后我从 7GB 的服务器升级到了 14GB 的服务器。查询速度也好不到哪里去。
服务器上的观察
- 我可以看到,内存使用量从未真正超过 2MB。
- 使用 LIKE 语句运行查询时,磁盘读取超出图表。
- 与 id(主键)匹配时,查询速度非常好
postgresql.conf 文件与默认设置相比仅有少量更改。请注意,我从以下博客文章中获取了其中一些建议:http://www.gabrielweinberg.com/blog/2011/05/postgresql.html。
对 conf 的更改:
shared_buffers = 512MB
checkpoint_segments = 10
(我更改了 checkpoint_segments,因为我在加载 CSV 文件时收到了很多警告......虽然生产数据库不会非常密集,所以如果需要可以将其改回 3...)
cpu_index_tuple_cost = 0.0005
effective_cache_size = 10GB # recommendation in the blog post was 2GB...
在服务器本身的任务管理器 -> 性能选项卡中,以下可能是可以提供帮助的相关位:
CPU:很少超过 2%(无论运行什么查询......当我导入 6GB CSV 文件时,它达到了 11%)
内存:1.5/14.0GB (11%)
有关内存的更多详细信息:
- 使用中:1.4GB
- 可用:12.5GB
- 已提交 1.9/16.1 GB
- 缓存:835MB
- 分页池:95.2MB
- 非分页池:71.2 MB
问题
- 如何确保索引位于内存中(前提是它不会对内存太大)?我需要在这里进行配置调整吗?
- 在这里实施我自己的搜索索引(例如 Lucene)是更好的选择吗?
- 即使我可以解决内存中的索引问题,postgres 中的全文索引功能是否会显着提高性能?
感谢阅读。
【问题讨论】:
-
需要考虑的几件事:创建全文搜索索引并匹配字符串几乎总是比使用“喜欢”更好。当查询不好时,无论您添加多少内存,它都不会改变性能。 PG的全文搜索就可以了,除非你有数百万条记录那么你应该考虑弹性搜索或类似的东西。
-
@SamD 我一般同意,但 FTS 并不适合所有工作。我想你不能有用地 lex 它你不能 FTS 它。除非您喜欢编写自定义 FTS 解析器,否则如果它的结构很奇怪,则同上。在这些情况下,pg_tgrm 索引 + LIKE 可能很有用。
标签: sql postgresql configuration indexing