Tại sao Postgres ngồi không hoạt động 95%, không có tệp I / O?


8

Tôi có một ngăn xếp TileMill / PostGIS chạy trên máy ảo Ubuntu 12.04 lõi 8 trên đám mây OpenStack. Đó là bản dựng lại của một hệ thống rất giống nhau đang chạy tốt trên phần cứng rất giống nhau (cùng một đám mây, nhưng phần cứng vật lý khác nhau, tôi tin) vào tuần trước. Tôi đã cố gắng xây dựng lại ngăn xếp chính xác như cũ (sử dụng một số tập lệnh tôi đã xây dựng).

Mọi thứ đều chạy, nhưng cơ sở dữ liệu đang thực hiện các truy vấn cực kỳ chậm, biểu hiện cuối cùng với việc tạo ra các ô rất chậm. Một truy vấn mẫu (đếm số lượng quán rượu trong bán kính của mỗi thị trấn ở Úc), trước đây mất khoảng 10-20 giây, giờ mất hơn 10 phút:

explain (analyze, buffers) update places set pubs = 
(select count(*) from planet_osm_point p where p.amenity = 'pub' and st_dwithin(p.way,places.way,scope)) +
(select count(*) from planet_osm_polygon p where p.amenity = 'pub' and st_dwithin(p.way,places.way,scope)) ;
 Update on places  (cost=0.00..948254806.93 rows=9037 width=160) (actual time=623321.558..623321.558 rows=0 loops=1)
   Buffers: shared hit=132126300
   ->  Seq Scan on places  (cost=0.00..948254806.93 rows=9037 width=160) (actual time=68.130..622931.130 rows=9037 loops=1)
         Buffers: shared hit=132107781
         SubPlan 1
           ->  Aggregate  (cost=12.95..12.96 rows=1 width=0) (actual time=0.187..0.188 rows=1 loops=9037)
                 Buffers: shared hit=158171
                 ->  Index Scan using planet_osm_point_index on planet_osm_point p  (cost=0.00..12.94 rows=1 width=0) (actual time=0.163..0.179 rows=0 loops=9037)
                       Index Cond: (way && st_expand(places.way, (places.scope)::double precision))
                       Filter: ((amenity = 'pub'::text) AND (places.way && st_expand(way, (places.scope)::double precision)) AND _st_dwithin(way, places.way, (places.scope)::double precision))
                       Buffers: shared hit=158171
         SubPlan 2
           ->  Aggregate  (cost=104917.24..104917.25 rows=1 width=0) (actual time=68.727..68.728 rows=1 loops=9037)
                 Buffers: shared hit=131949237
                 ->  Seq Scan on planet_osm_polygon p  (cost=0.00..104917.24 rows=1 width=0) (actual time=68.138..68.716 rows=0 loops=9037)
                       Filter: ((amenity = 'pub'::text) AND (way && st_expand(places.way, (places.scope)::double precision)) AND (places.way && st_expand(way, (places.scope)::double precision)) AND _st_dwithin(way, places.way, (places.scope)::double precision))
                       Buffers: shared hit=131949237
 Total runtime: 623321.801 ms

(Tôi bao gồm truy vấn này như một triệu chứng, không trực tiếp giải quyết vấn đề. Truy vấn cụ thể này chỉ được chạy một lần một tuần hoặc lâu hơn.)

Máy chủ có 32 GB RAM và tôi đã định cấu hình Postgres như sau (theo lời khuyên tìm thấy trên web):

shared_buffers = 8GB
autovacuum = on
effective_cache_size = 8GB
work_mem = 128MB
maintenance_work_mem = 64MB
wal_buffers = 1MB
checkpoint_segments = 10

iostat cho thấy không có gì được đọc, một chút dữ liệu được ghi (không biết ở đâu hoặc tại sao) và CPU nhàn rỗi 95%:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.40    0.00    0.00    0.11    0.00   94.49

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
vda               0.20         0.00         0.80          0          8
vdb               2.30         0.00        17.58          0        176

Đầu ra mẫu từ vmstat:

  procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
...
 1  0      0 18329748 126108 12600436    0    0     0    18  148  140  5  0 95  0
 2  0      0 18329400 126124 12600436    0    0     0     9  173  228  5  0 95  0

Nắm chặt ống hút, tôi chuyển thư mục dữ liệu Postgres từ vda sang vdb nhưng tất nhiên điều đó không có gì khác biệt.

Vì vậy, tôi đang thua lỗ. Tại sao Postgres chỉ sử dụng 5% CPU có sẵn khi nó không chờ đợi bất kỳ I / O nào? Tôi hoan nghênh mọi đề xuất để điều tra thêm, các công cụ khác, những điều ngẫu nhiên để thử.

Cập nhật

Tôi đã chụp nhanh máy chủ và khởi chạy nó trên một phần khác của cùng một đám mây (một vùng khả dụng khác nhau). Kết quả hơi kỳ lạ. vmstattrên máy chủ này báo cáo mức sử dụng CPU 12% (mà bây giờ tôi hiểu là giá trị mong đợi cho một truy vấn Postgres duy nhất trên máy ảo 8 lõi) - mặc dù thời gian thực hiện truy vấn thực tế gần như giống hệt nhau (630 giây so với 623).

Bây giờ tôi nhận ra rằng truy vấn cụ thể này có thể không phải là một mẫu tốt vì lý do này: nó chỉ có thể sử dụng một lõi và đó là một update(trong khi kết xuất gạch chỉ là selects).

Tôi cũng không nhận thấy explainrằng dường như planet_osm_polygonkhông sử dụng một chỉ mục. Đó cũng có thể là nguyên nhân, vì vậy tôi sẽ theo đuổi điều đó tiếp theo.

Cập nhật2

Vấn đề dường như chắc chắn là chỉ số hành tinh_osm_polygon không được sử dụng. Có hai (một được tạo bởi osm2pgsql, một được tạo bởi tôi theo một số hướng dẫn ngẫu nhiên):

CREATE INDEX idx_planet_osm_polygon_tags
  ON planet_osm_polygon
  USING gist
  (tags);


CREATE INDEX planet_osm_polygon_pkey
  ON planet_osm_polygon
  USING btree
  (osm_id);

Các số liệu thống kê về hành tinh_osm_polygon và hành tinh_osm_point khá lộ liễu, tôi nghĩ:

hành tinh_osm_polygon:

Sequential Scans    194204  
Sequential Tuples Read  60981018608 
Index Scans 1574    
Index Tuples Fetched    0

hành tinh_osm_point:

Sequential Scans    1142    
Sequential Tuples Read  12960604    
Index Scans 183454  
Index Tuples Fetched    43427685

Nếu tôi đọc đúng, Postgres đã tìm kiếm hành tinh_osm_polygon 1574 lần, nhưng thực sự không bao giờ tìm thấy bất cứ điều gì, vì vậy đã thực hiện một số lượng lớn các tìm kiếm vũ phu.

Câu hỏi mới: tại sao?

Giải đáp bí ẩn

Nhờ câu trả lời của Frederik Ramm , câu trả lời hóa ra khá đơn giản: vì một số lý do không có chỉ số không gian. Thật là tầm thường khi tái tạo chúng:

create index planet_osm_polygon_polygon on planet_osm_polygon using gist(way);
create index planet_osm_polygon_point on planet_osm_point using gist(way);

Chạy truy vấn đó bây giờ mất 4,6 giây. Chỉ số không gian quan trọng! :)


Tôi nhận ra rằng mục này khá cũ, tuy nhiên tôi đang gặp một vấn đề tương tự. Tôi không thể tạo hành tinh_osm_polygon_point hai lần vì chỉ mục đã tồn tại. Tuy nhiên, chỉ số này được gọi là gì không quan trọng, phải không?
Sebastian Borggrewe

Chà nếu chỉ số tồn tại, tại sao bạn muốn tạo một cái khác? Nhưng trong mọi trường hợp, bạn có thể bỏ cái cũ hoặc đổi tên cái mới.
Steve Bennett

Tôi chỉ hỏi vì cả hai chỉ mục: tạo chỉ mục hành tinh_osm_polygon_point trên hành tinh_osm_polygon bằng cách sử dụng ý chính (cách); tạo chỉ mục hành tinh_osm_polygon_point trên hành tinh_osm_point bằng cách sử dụng ý chính (cách); được đặt tên hành tinh_osm_polygon_point, có vẻ như là một sai lầm trừ khi tôi thiếu một cái gì đó.
Sebastian Borggrewe

Oh! Tôi đã không hiểu. Có một lỗi đánh máy trong câu trả lời của tôi.
Steve Bennett

Cảm ơn Steve, bạn cũng có thể sửa lỗi đánh máy trong câu trả lời của bạn để tham khảo trong tương lai. Cảm ơn.
Sebastian Borggrewe

Câu trả lời:


4

Chạy đầu ra Giải thích Anlayze của bạn thông qua giải thích.depesz.com nhấn mạnh rằng phần lớn sự chậm chạp xuất phát từ hành động này:

Seq Scan on planet_osm_polygon p 

Đó có phải là chỉ mục trước? Bạn có thể lập chỉ mục bây giờ?

Bằng cách tìm kiếm khu vực có vấn đề đó, tôi cũng tìm thấy một câu hỏi và trả lời liên quan trên trang web Bản đồ đường phố mở:


Cảm ơn đã chỉ ra điều này - tôi đã bỏ lỡ điều đó. Thực tế có hai chỉ số trên bảng này. Cập nhật câu hỏi của tôi với nhiều thông tin hơn.
Steve Bennett

Oh - liên kết đó đã có câu trả lời. Có, mặc dù có "chỉ mục", nhưng nó chỉ nằm trên trường ID, không phải trường hình học thực tế ("cách") - vì vậy vô dụng đối với việc lập chỉ mục không gian. Ý kiến ​​của Frederik có câu trả lời.
Steve Bennett

4

PostgreSQL chỉ có thể sử dụng một lõi cho bất kỳ truy vấn nào. Nó đạt được hiệu suất song song tốt với nhiều truy vấn đồng thời, nhưng không được hưởng lợi từ số lượng lõi lớn cho khối lượng công việc chỉ bằng một vài truy vấn rất lớn. Vì vậy, nếu bạn chỉ chạy một truy vấn duy nhất thì 5% không có gì đáng ngạc nhiên, mặc dù tôi hy vọng nó sẽ là 12% trên hệ thống 8 lõi.

Việc thiếu iowait cho thấy có lẽ nó không đau khổ cho I / O đĩa.

Vì vậy - nó dường như không bị tắc nghẽn trên CPU hoặc trên I / O.

Có thể truy vấn chỉ đơn giản là bị khóa trong một thời gian bởi một khóa? Kiểm tra pg_stat_activitytruy vấn và tham gia pg_locksđể xem có khóa nào không được cấp không. (Có các truy vấn đóng hộp về giám sát khóa PG).

Điều tiếp theo cần làm là chạy một số thử nghiệm hệ thống cấp thấp hơn. Chạy pg_test_fsync, sử dụng các bài kiểm tra CPU và I / O của sysbench, v.v ... Nếu chúng cũng hoạt động kém, hãy nâng cao nó với nhà cung cấp dịch vụ lưu trữ của bạn.

Bạn cũng nên thu thập perf top -ađầu ra một chút, xem những gì nó thực sự làm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.