我有以下包含流量测量数据的简单表:
CREATE TABLE "TrafficData"
(
"RoadID" character varying NOT NULL,
"DateID" numeric NOT NULL,
"ExactDateTime" timestamp NOT NULL,
"CarsSpeed" numeric NOT NULL,
"CarsCount" numeric NOT NULL
)
CREATE INDEX "RoadDate_Idx" ON "TrafficData" USING btree ("RoadID", "DateID");
RoadID列唯一标识正在记录其数据的道路,而DateID标识数据的一年中的日期(1..365) - 基本上是ExactDateTime的四舍五入表示。
我有大约100.000.000行; “RoadID”列中有1.000个不同的值,“DateID”列中有365个不同的值。
然后我运行以下查询:
SELECT * FROM "TrafficData"
WHERE "RoadID"='Station_1'
AND "DateID">20100610 AND "DateID"<20100618;
这需要三个令人难以置信的秒才能完成,而我无法为我的生活找到原因。
EXPLAIN ANALYZE给出了以下输出:
Bitmap Heap Scan on "TrafficData" (cost=104.84..9743.06 rows=2496 width=47) (actual time=35.112..2162.404 rows=2016 loops=1)
Recheck Cond: ((("RoadID")::text = 'Station_1'::text) AND ("DateID" > 20100610::numeric) AND ("DateID" < 20100618::numeric))
-> Bitmap Index Scan on "RoadDate_Idx" (cost=0.00..104.22 rows=2496 width=0) (actual time=1.637..1.637 rows=2016 loops=1)
Index Cond: ((("RoadID")::text = 'Station_1'::text) AND ("DateID" > 20100610::numeric) AND ("DateID" < 20100618::numeric))
Total runtime: 2163.985 ms
我的规格:
我非常感谢任何有用的指示!
答案 0 :(得分:4)
缓慢的部分是从表中获取数据,因为索引访问速度似乎非常快。您可以优化RAM使用参数(请参阅http://wiki.postgresql.org/wiki/Performance_Optimization和http://www.varlena.com/GeneralBits/Tidbits/perf.html),或者通过发出CLUSTER命令来优化表中数据的布局(请参阅http://www.postgresql.org/docs/8.3/static/sql-cluster.html)。
CLUSTER "TrafficData" USING "RoadDate_Idx";
应该这样做。
答案 1 :(得分:2)
添加到Daniel的答案中,群集操作是一个关闭过程,重新安排磁盘上的数据。目的是从较少的磁盘块中获取2000个结果行。
由于这是虚拟数据,用于了解如何快速查询它,我建议重新加载它,其模式更接近于生成时的加载方式。我想这些数据一次只能生成一天,这将有效地导致DateID
与磁盘上的位置之间的强相关性。如果是这种情况,那么我要按DateID
进行聚类,或者将测试数据拆分为365个单独的加载,然后重新加载。
如果没有它,并且随机生成数据,您很可能不得不执行超过2000次的磁盘头搜索。
我还会检查您在Windows 7上运行的任何其他内容是否为这些您不需要的读取添加时间,例如确保读取的块不包含病毒签名,或同时执行自动调度的磁盘碎片整理(导致磁盘头几乎不会接近上次读取数据库块的位置)。
答案 2 :(得分:0)
AND "DateID">20100610 AND "DateID"<20100618;
- &gt; DateID BETWEEN 20100611 AND 20100617;
RoadID
设为文本字段