2015-09-09 14 views
5

Dưới đây truy vấn mất khoảng 15 giây để trả về dữ liệu mặc dù có chỉ mục và id làm khóa chính.Thứ tự theo truy vấn trên cột dấu thời gian là rất chậm

select id from my_table order by insert_date offset 0 limit 1 

Các giải thích phân tích như sau

"Limit (cost=1766417.72..1766417.72 rows=1 width=12) (actual time=32479.440..32479.441 rows=1 loops=1)" 
" -> Sort (cost=1766417.72..1797117.34 rows=12279848 width=12) (actual time=32479.437..32479.437 rows=1 loops=1)" 
"  Sort Key: insert_date" 
"  Sort Method: top-N heapsort Memory: 25kB" 
"  -> Seq Scan on my_table (cost=0.00..1705018.48 rows=12279848 width=12) (actual time=0.006..21338.401 rows=12108916 loops=1)" 
"Total runtime: 32479.476 ms" 

bảng của tôi có vài cột khác. Nhưng kiểu cho insert_date

insert_date timestamp without time zone NOT NULL DEFAULT now(), 

Tôi có một chỉ mục trên cột ngày cụ thể đó là

CREATE INDEX my_table_insert_date_indx 
    ON my_table 
    USING btree 
    (insert_date) 
TABLESPACE somexyz_idx_ts; 

ít giá trị từ postgresql.conf file:

shared_buffers = more than 1GB ## just for an example 
temp_buffers = more than 1GB 
work_mem = more than 1GB 
maintenance_work_mem = more than 1GB 
dynamic_shared_memory_type = posix 
default_statistics_target = 10000 
autovacuum = on 
random_page_cost = 2.0 
cpu_index_tuple_cost = 0.0005 

Tôi đang sử dụng postgres 9,3 ngay bây giờ.

CẬP NHẬT ::

Tôi chỉ cần chạy các truy vấn dưới đây một thời gian trước:

select insert_date, count(*) from my_table group by insert_date 

và đầu vài từ kết quả là:

"2015-04-02 00:00:00";3718104 
"2015-04-03 00:00:00";6410253 
"2015-04-04 00:00:00";538247 
"2015-04-05 00:00:00";1228877 
"2015-04-06 00:00:00";131248 

Tôi có khoảng 12 triệu bản ghi trên bảng đó. Và số lượng trên gần như gần với tổng số đó.

Không chắc chắn, nhưng nó có thể là một vấn đề mà chỉ mục đã được tạo ra trên một cột mà có tấn giá trị trùng lặp? Nếu nó là sự thật, thì chúng ta có cách nào không?

+0

Có lẽ một nơi tốt hơn để đặt câu hỏi: [dba.stackexchange.com] (http://dba.stackexchange.com) –

+0

Có một câu hỏi tương tự gần đây trên SO, và tôi nghĩ rằng kết luận có thể là do 9.4 tốt hơn khi đặt hàng bằng cột được lập chỉ mục để tránh sắp xếp. Có thể muốn tìm kiếm câu hỏi đó. –

+0

Vui lòng kiểm tra cùng một truy vấn với 'set enable_seqscan = off;' và hiển thị kết quả phân tích giải nghĩa. Chỉ số và bảng của bạn lớn đến mức nào? '\ di + my_table_insert_date_indx',' \ dt + my_table' lệnh trong psql sẽ hiển thị kích cỡ – alexius

Trả lời

2

Truy vấn của bạn chạy nhanh hơn 160000 lần trên máy bằng cả PostgreSQL 9.3 và 9.4. Máy của tôi không có gì đặc biệt cả.

-- From PostgreSQL 9.4; 9.3 is similar. 
show shared_buffers; -- 128MB 
show temp_buffers; -- 8MB 
show work_mem; -- 4MB 
show maintenance_work_mem; -- 64MB 
show dynamic_shared_memory_type; -- posix 
show default_statistics_target; -- 100 
show autovacuum; -- on 
show random_page_cost; -- 4 
show cpu_index_tuple_cost; -- 0.005 

Chuẩn bị

Hãy xây dựng một bảng. (Bạn nên làm điều này trong câu hỏi của bạn.)

create table my_table (
    id serial primary key, 
    insert_date timestamp not null 
); 

-- Round numbers of rows. 
insert into my_table(insert_date) 
select timestamp '2015-04-02 00:00:00' 
from generate_series(1, 3000000) n; 

insert into my_table(insert_date) 
select timestamp '2015-04-03 00:00:00' 
from generate_series(1, 6000000) n; 

insert into my_table(insert_date) 
select timestamp '2015-04-04 00:00:00' 
from generate_series(1, 500000) n; 

insert into my_table(insert_date) 
select timestamp '2015-04-05 00:00:00' 
from generate_series(1, 1200000) n; 

insert into my_table(insert_date) 
select timestamp '2015-04-06 00:00:00' 
from generate_series(1, 131000) n; 

Tạo chỉ mục và cập nhật thống kê.

create index on my_table (insert_date); 
analyze my_table; 

PostgreSQL 9.4

Bây giờ, những loại kế hoạch thực hiện sao chúng ta nhận được từ truy vấn đầu tiên của bạn?

explain analyze 
select id from my_table order by insert_date offset 0 limit 1; 
 
"Limit (cost=0.43..0.48 rows=1 width=12) (actual time=0.014..0.014 rows=1 loops=1)" 
" -> Index Scan using my_table_insert_date_idx on my_table (cost=0.43..540656.27 rows=11200977 width=12) (actual time=0.012..0.012 rows=1 loops=1)" 
"Planning time: 0.195 ms" 
"Execution time: 0.032 ms" 

PostgreSQL 9.3

explain analyze 
select id from my_table order by insert_date offset 0 limit 1; 
 
"Limit (cost=0.43..0.47 rows=1 width=12) (actual time=0.058..0.059 rows=1 loops=1)" 
" -> Index Scan using my_table_insert_date_idx on my_table (cost=0.43..339814.36 rows=10830995 width=12) (actual time=0.057..0.057 rows=1 loops=1)" 
"Total runtime: 0.098 ms" 

truy vấn của bạn

select id from my_table order by insert_date offset 0 limit 1; 

là không xác định. Có 3 triệu hàng có insert_date thấp nhất (ngày xuất hiện đầu tiên, theo mệnh đề ORDER BY). Bạn chọn một trong số 3 triệu. PostgreSQL không đảm bảo bạn sẽ nhận được cùng một id mỗi lần.

Nếu bạn không quan tâm đến 3 triệu id trả về, bạn có thể thể hiện truy vấn một cách khác nhau. Nhưng tôi không nghĩ rằng việc thể hiện nó sẽ khác nhau sẽ giúp bạn tăng tốc 160k lần.

Một số cài đặt bạn đã bao gồm có thể được thay đổi cho một truy vấn cụ thể. Vì vậy, bạn có thể làm một cái gì đó như thế này.

-- Don't commit or rollback . . . 
begin transaction; 
set local work_mem = '8 MB'; 

explain analyze 
select id from my_table order by insert_date offset 0 limit 1; 
-- Displays the result. 

Cam kết hoặc khôi phục thủ công.

commit; 

Cài đặt work_mem của bạn trở về giá trị được đặt khi khởi động máy chủ.

show work_mem; -- 4MB 
Các vấn đề liên quan