1

我有一个 PostgreSQL 数据库,其中包含很多行 ~160,000,000。数据库基本上是一组网络日志。有一个名为 time 的列,它是一个时间戳。基本上,对于每个独特的时间,网络上的每台机器都有一个日志。因此,有多行具有相同的时间戳。IE

time    ip             value
2:00    192.168.1.1    5
2:00    192.168.1.2    4
2:00    192.168.1.3    5
3:00    192.168.1.1    3
3:00    192.168.1.2    5
3:00    192.168.1.3    2
etc     etc

现在我已经按时间为这个数据库创建了一个索引,因为这是我经常查询的字段。

i.e. select * from networklogs where time = '2:00' and value = 5

在不使用索引的情况下,每个查询大约需要 2 分钟,因为查询必须扫描整个数据库。我创建了索引,以便我的查询将找到包含匹配时间的数据子集,然后根据此处的另一个值进行过滤,因此我希望查询会快得多。

但是现在查询似乎需要更长的时间......

这很奇怪,因为在 pgAdmin 中它解释了查询将使用时间索引,并且时间索引将数据从总共 160,000,000 项中缩小到约 800,000 项,然后查询上的过滤器将此数据缩小到 1,700 项。这个解释需要 17 毫秒,但是如果我运行查询则需要 3 分钟。

这应该比在 160,000,000 个项目上搜索两个匹配条件更快!

我无法弄清楚为什么它没有更快,我想知道即使 pgAdmin 将查询解释为使用时间索引,它是否在执行查询时实际使用它?

有没有人有任何想法或建议?

谢谢,詹姆斯

更新:我对以下命令运行了 EXPLAIN ANALYZE:

explain analyze select latitude,longitude from networklogs where value = 5 and time = '2:00'

结果是:

"Bitmap Heap Scan on networklogs  (cost=13178.17..1488620.94 rows=848 width=19) (actual time=3507.923..278760.509 rows=33 loops=1)"
"  Recheck Cond: (time = '2:00'::timestamp without time zone)"
"  Rows Removed by Index Recheck: 38302021"
"  Filter: (value = 5)"
"  Rows Removed by Filter: 882873"
"  ->  Bitmap Index Scan on timeindex  (cost=0.00..13177.95 rows=530111 width=0) (actual time=695.771..695.771 rows=882906 loops=1)"
"        Index Cond: (time = '2:00'::timestamp without time zone)"
"Total runtime: 278764.148 ms"
4

2 回答 2

3

如果这些主要是您要执行搜索的参数,我建议在它们上创建一个多重索引。因为,在您的实际情况下,数据库准时有一个索引,因此它能够知道哪些行与此条件匹配,但是它必须从索引给定的所有不同位置获取它们,然后检查辅助条件。

CREATE INDEX time_and_value ON networklogs (time, value);

使用这个索引,数据库不必为了检查另一个条件而获取数据,它会简单地获取它知道已经匹配搜索条件的数据。顺序当然很重要。

我看到您正在使用纬度和经度数据,也许使用该point类型会很好,因此您将能够使用 Postgres 默认提供的所有几何运算符。这些类型的数据也可以被索引。

于 2012-12-03T16:41:19.627 回答
2

PostgreSQL 有EXPLAIN 和 EXPLAIN ANALYZE来检查查询是如何运行的。PG Admin 很可能使用 EXPLAIN 来告诉您查询将如何运行;您可以使用 EXPLAIN ANALYZE 获得更准确的结果,它实际运行查询并从实际运行中生成统计信息。即使它按预期使用索引,您至少可以看到时间花在了哪里。

于 2012-12-03T15:54:45.787 回答