Hệ thống của chúng tôi ghi rất nhiều dữ liệu (loại hệ thống Dữ liệu lớn). Hiệu suất viết là đủ tốt cho nhu cầu của chúng tôi nhưng hiệu suất đọc thực sự quá chậm.
Cấu trúc khóa chính (ràng buộc) tương tự cho tất cả các bảng của chúng tôi:
timestamp(Timestamp) ; index(smallint) ; key(integer).
Một bảng có thể có hàng triệu hàng, thậm chí hàng tỷ hàng và yêu cầu đọc thường dành cho một khoảng thời gian cụ thể (dấu thời gian / chỉ mục) và thẻ. Thông thường có một truy vấn trả về khoảng 200 nghìn dòng. Hiện tại, chúng tôi có thể đọc khoảng 15k dòng mỗi giây nhưng chúng tôi cần phải nhanh hơn 10 lần. Điều này có thể và nếu vậy, làm thế nào?
Lưu ý: PostgreSQL được đóng gói với phần mềm của chúng tôi, vì vậy phần cứng khác nhau từ máy khách này sang máy khách khác.
Nó là một VM được sử dụng để thử nghiệm. Máy chủ của VM là Windows Server 2008 R2 x64 với 24.0 GB RAM.
Thông số máy chủ (VMWare máy ảo)
Server 2008 R2 x64
2.00 GB of memory
Intel Xeon W3520 @ 2.67GHz (2 cores)
postgresql.conf
tối ưu hóa
shared_buffers = 512MB (default: 32MB)
effective_cache_size = 1024MB (default: 128MB)
checkpoint_segment = 32 (default: 3)
checkpoint_completion_target = 0.9 (default: 0.5)
default_statistics_target = 1000 (default: 100)
work_mem = 100MB (default: 1MB)
maintainance_work_mem = 256MB (default: 16MB)
Bảng định nghĩa
CREATE TABLE "AnalogTransition"
(
"KeyTag" integer NOT NULL,
"Timestamp" timestamp with time zone NOT NULL,
"TimestampQuality" smallint,
"TimestampIndex" smallint NOT NULL,
"Value" numeric,
"Quality" boolean,
"QualityFlags" smallint,
"UpdateTimestamp" timestamp without time zone, -- (UTC)
CONSTRAINT "PK_AnalogTransition" PRIMARY KEY ("Timestamp" , "TimestampIndex" , "KeyTag" ),
CONSTRAINT "FK_AnalogTransition_Tag" FOREIGN KEY ("KeyTag")
REFERENCES "Tag" ("Key") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE,
autovacuum_enabled=true
);
Truy vấn
Truy vấn mất khoảng 30 giây để thực thi trong pgAdmin3, nhưng chúng tôi muốn có kết quả tương tự dưới 5 giây nếu có thể.
SELECT
"AnalogTransition"."KeyTag",
"AnalogTransition"."Timestamp" AT TIME ZONE 'UTC',
"AnalogTransition"."TimestampQuality",
"AnalogTransition"."TimestampIndex",
"AnalogTransition"."Value",
"AnalogTransition"."Quality",
"AnalogTransition"."QualityFlags",
"AnalogTransition"."UpdateTimestamp"
FROM "AnalogTransition"
WHERE "AnalogTransition"."Timestamp" >= '2013-05-16 00:00:00.000' AND "AnalogTransition"."Timestamp" <= '2013-05-17 00:00:00.00' AND ("AnalogTransition"."KeyTag" = 56 OR "AnalogTransition"."KeyTag" = 57 OR "AnalogTransition"."KeyTag" = 58 OR "AnalogTransition"."KeyTag" = 59 OR "AnalogTransition"."KeyTag" = 60)
ORDER BY "AnalogTransition"."Timestamp" DESC, "AnalogTransition"."TimestampIndex" DESC
LIMIT 500000;
Giải thích 1
"Limit (cost=0.00..125668.31 rows=500000 width=33) (actual time=2.193..3241.319 rows=500000 loops=1)"
" Buffers: shared hit=190147"
" -> Index Scan Backward using "PK_AnalogTransition" on "AnalogTransition" (cost=0.00..389244.53 rows=1548698 width=33) (actual time=2.187..1893.283 rows=500000 loops=1)"
" Index Cond: (("Timestamp" >= '2013-05-16 01:00:00-04'::timestamp with time zone) AND ("Timestamp" <= '2013-05-16 15:00:00-04'::timestamp with time zone))"
" Filter: (("KeyTag" = 56) OR ("KeyTag" = 57) OR ("KeyTag" = 58) OR ("KeyTag" = 59) OR ("KeyTag" = 60))"
" Buffers: shared hit=190147"
"Total runtime: 3863.028 ms"
Giải thích 2
Trong thử nghiệm mới nhất của tôi, phải mất 7 phút để chọn dữ liệu của tôi! Xem bên dưới:
"Limit (cost=0.00..313554.08 rows=250001 width=35) (actual time=0.040..410721.033 rows=250001 loops=1)"
" -> Index Scan using "PK_AnalogTransition" on "AnalogTransition" (cost=0.00..971400.46 rows=774511 width=35) (actual time=0.037..410088.960 rows=250001 loops=1)"
" Index Cond: (("Timestamp" >= '2013-05-22 20:00:00-04'::timestamp with time zone) AND ("Timestamp" <= '2013-05-24 20:00:00-04'::timestamp with time zone) AND ("KeyTag" = 16))"
"Total runtime: 411044.175 ms"