我正在使用postgresql 9.4.6。
有以下实体:
CREATE TABLE user (id CHARACTER VARYING NOT NULL PRIMARY KEY);
CREATE TABLE group (id CHARACTER VARYING NOT NULL PRIMARY KEY);
CREATE TABLE group_member (
id CHARACTER VARYING NOT NULL PRIMARY KEY,
gid CHARACTER VARYING REFERENCES group(id),
uid CHARACTER VARYING REFERENCES user(id));
我分析了那个查询:
explain analyze select x2."gid" from "group_member" x2 where x2."uid" = 'a1';
我有几个结果。在每次结果之前,我刷新了操作系统缓存并重新启动了postgres:
# /etc/init.d/postgresql stop
# sync
# echo 3 > /proc/sys/vm/drop_caches
# /etc/init.d/postgresql start
分析结果如下:
1)成本= 4.17..11.28 ,索引:
create index "group_member_gid_idx" on "group_member" ("gid");
create index "group_member_uid_idx" on "group_member" ("uid");
Bitmap Heap Scan on group_member x2 (cost=4.17..11.28 rows=3 width=32) (actual time=0.021..0.021 rows=0 loops=1)
Recheck Cond: ((uid)::text = 'a1'::text)
-> Bitmap Index Scan on group_member_uid_idx (cost=0.00..4.17 rows=3 width=0) (actual time=0.005..0.005 rows=0 loops=1)
Index Cond: ((uid)::text = 'a1'::text)
Planning time: 28.641 ms
Execution time: 0.359 ms
2)成本= 7.97..15.08 ,索引:
create unique index "group_member_gid_uid_idx" on "group_member" ("gid","uid");
Bitmap Heap Scan on group_member x2 (cost=7.97..15.08 rows=3 width=32) (actual time=0.013..0.013 rows=0 loops=1)
Recheck Cond: ((uid)::text = 'a1'::text)
-> Bitmap Index Scan on group_member_gid_uid_idx (cost=0.00..7.97 rows=3 width=0) (actual time=0.006..0.006 rows=0 loops=1)
Index Cond: ((uid)::text = 'a1'::text)
Planning time: 0.132 ms
Execution time: 0.047 ms
3)成本= 0.00..16.38 ,没有任何索引:
Seq Scan on group_member x2 (cost=0.00..16.38 rows=3 width=32) (actual time=0.002..0.002 rows=0 loops=1)
Filter: ((uid)::text = 'a1'::text)
Planning time: 42.599 ms
Execution time: 0.402 ms
结果#3更有效吗?为什么?
修改 在实践中,表(group,user,group_members)中将有许多行。关于> 100万。
答案 0 :(得分:6)
在分析查询时,小数据集上的成本和查询计划通常不是较大数据集上性能的可靠指南。并且,SQL更关注的是更大的数据集,而不是简单的小数据集。
从磁盘读取数据通常是查询性能的驱动因素。使用索引的主要目的是减少正在读取的数据页的数量。如果表中的所有数据都适合单个数据页,那么减少页面读取次数的机会就不多了:读取一个页面需要相同的时间,无论页面有一个记录还是100条记录。 (通过页面读取以找到正确的记录也会产生开销,而索引会识别页面上的特定记录。)
索引会产生开销,但通常比读取数据页要少得多。索引本身需要读入内存 - 这意味着两个页面被读入内存而不是一个。有人可能会争辩说,对于适合一两页的表格,使用索引可能不是一个很大的优势。
尽管使用索引(在这种情况下)确实需要更长的时间,但在几分之一毫秒内测量的性能差异通常与大多数数据库任务没有密切关系。如果要查看索引是否正常工作,请在表中放置100,000行并运行相同的测试。您将看到没有索引的版本大致与表中的数据量成比例;索引的版本相对恒定(实际上,缩放更像是表中记录数的日志)。