PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Nghiên cứu độ chậm của PostGIS (ấn bản 2019)

Ngay khi năm ngoái vừa kết thúc, một trong những khách hàng lâu năm của chúng tôi đã đến với chúng tôi vì một trong những truy vấn PostgreSQL tồn tại từ lâu của họ liên quan đến các phép tính hình học PostGIS chậm hơn nhiều đối với các giá trị cụ thể. Chúng tôi đã nghiên cứu vấn đề và tìm ra cách giải quyết nó; đọc tiếp! Những gì chúng tôi đã tìm ra là nguyên nhân của vấn đề sẽ khiến bạn ngạc nhiên!

Quan sát ban đầu được khách hàng của chúng tôi báo cáo là đang chạy một truy vấn liên quan đến ST_DistanceSpheroid mất khoảng 7 mili giây khi được yêu cầu trả lại khoảng cách đến POINT(33.681953 23.155994) trên một hình cầu cụ thể, nhưng nếu điểm đó được chuyển đến POINT(33.681953 23.1559941) (chênh lệch chỉ 0.0000001 ) thì mất 0,13 mili giây. Nhanh hơn 60 lần! Điều gì trên Trái đất (một hình cầu khác!) Có thể đang xảy ra?

Ban đầu, chúng tôi không thể tái tạo độ chậm trong môi trường thử nghiệm của mình. Trong tầm tay của chúng tôi, cả hai truy vấn sẽ thực hiện nhanh chóng như nhau, không bị chậm lại. Chúng tôi đã tìm hiểu kỹ các phiên bản phần mềm cụ thể đang được sử dụng với suy nghĩ rằng có thể cần phải cập nhật. Chúng tôi đã sử dụng các phiên bản do khách hàng báo cáo:PostgreSQL 10.11, PostGIS 2.4.4, libproj 4.93. Chúng tôi quay lại thời kỳ hang động bằng cách hạ cấp xuống các phiên bản chính xác đó, nhưng không thành công.

Cuối cùng, chúng tôi nhận ra rằng khách hàng đang sử dụng Ubuntu 18.04, vì vậy chúng tôi đã thử điều đó… và xin lỗi, sự cố đã tái tạo ở đó. Chỉ cần nói rằng chúng tôi đã chớp lấy cơ hội lập hồ sơ truy vấn trong máy đó. Chúng tôi có cái này:

Samples: 224K of event 'cpu-clock', Event count (approx.): 56043500000
  Children      Self  Command   Shared Object           Symbol
+   84.86%     0.00%  postgres  [unknown]               [.] 0xffffffffffffffff
+   84.59%     0.00%  postgres  postgres                [.] DirectFunctionCall4Coll
+   84.58%     0.00%  postgres  postgis-2.5.so          [.] geometry_distance_spheroid
+   84.56%     0.00%  postgres  liblwgeom-2.5.so.0.0.0  [.] lwgeom_distance_spheroid
+   84.31%     0.19%  postgres  libm-2.27.so            [.] __sincos
+   84.18%     0.00%  postgres  libm-2.27.so            [.] __cos_local (inlined)
+   84.13%     0.00%  postgres  libm-2.27.so            [.] cslow2 (inlined)
+   84.05%     0.01%  postgres  libm-2.27.so            [.] __mpcos
+   83.95%     0.32%  postgres  libm-2.27.so            [.] __c32
+   83.87%     0.00%  postgres  postgres                [.] ExecInterpExpr
+   83.75%     0.00%  postgres  postgres                [.] standard_ExecutorRun
+   83.75%     0.00%  postgres  postgres                [.] ExecutePlan (inlined)
+   83.73%     0.00%  postgres  postgres                [.] ExecProcNode (inlined)
+   83.73%     0.00%  postgres  postgres                [.] ExecScan
+   83.67%     0.00%  postgres  postgres                [.] ExecProject (inlined)
+   83.67%     0.00%  postgres  postgres                [.] ExecEvalExprSwitchContext (inlined)
+   83.65%     0.00%  postgres  postgres                [.] _SPI_execute_plan
+   83.60%     0.00%  postgres  postgres                [.] _SPI_pquery (inlined)
+   83.49%     0.01%  postgres  plpgsql.so              [.] exec_stmts
+   83.49%     0.00%  postgres  plpgsql.so              [.] exec_stmt (inlined)
+   83.49%     0.00%  postgres  plpgsql.so              [.] exec_stmt_fori (inlined)
+   83.48%     0.00%  postgres  plpgsql.so              [.] exec_stmt_perform (inlined)
+   83.48%     0.00%  postgres  plpgsql.so              [.] exec_run_select
+   83.47%     0.00%  postgres  postgres                [.] SPI_execute_plan_with_paramlist
+   81.67%     0.01%  postgres  liblwgeom-2.5.so.0.0.0  [.] edge_distance_to_point
+   81.67%     0.00%  postgres  liblwgeom-2.5.so.0.0.0  [.] 0x00007f2ce1c2c0e6
+   61.85%    60.82%  postgres  libm-2.27.so            [.] __mul
+   54.83%     0.01%  postgres  liblwgeom-2.5.so.0.0.0  [.] sphere_distance
+   27.14%     0.00%  postgres  plpgsql.so              [.] exec_stmt_block
+   26.67%     0.01%  postgres  liblwgeom-2.5.so.0.0.0  [.] geog2cart
+   19.24%     0.00%  postgres  libm-2.27.so            [.] ss32 (inlined)
+   18.28%     0.00%  postgres  libm-2.27.so            [.] cc32 (inlined)
+   12.55%     0.76%  postgres  libm-2.27.so            [.] __sub
+   11.46%    11.40%  postgres  libm-2.27.so            [.] sub_magnitudes
+    8.15%     4.89%  postgres  libm-2.27.so            [.] __add
+    4.94%     0.00%  postgres  libm-2.27.so            [.] add_magnitudes (inlined)
+    3.18%     3.16%  postgres  libm-2.27.so            [.] __acr
+    2.66%     0.00%  postgres  libm-2.27.so            [.] mcr (inlined)
+    1.44%     0.00%  postgres  liblwgeom-2.5.so.0.0.0  [.] lwgeom_calculate_gbox_geodetic
+    1.44%     0.00%  postgres  liblwgeom-2.5.so.0.0.0  [.] ptarray_calculate_gbox_geodetic

Bạn nói vô nghĩa. Tuy nhiên, có điều gì đó rất tò mò về tiểu sử này… và bạn phải bỏ qua 26 dòng đầu tiên và tập trung vào __mul dòng ở đó. Thấy rằng 60,82% thời gian "tự"? (Tôi có thể nghe thấy âm thanh nhận ra tâm trí bạn vừa tạo ra). Vậy tại sao lại mất quá nhiều thời gian cho một số điểm nhất định trên hình cầu mà không phải những điểm khác? Và tại sao nó mất nhiều thời gian trong Ubuntu 18.04 mà không phải trong các máy khác? Tại sao nâng cấp PostGIS không khắc phục được sự cố?

Câu trả lời đã được gợi ý cho tôi khi tôi nhận ra điều hiển nhiên:PostGIS thực hiện rất nhiều lượng giác (sin, cosine, tiếp tuyến, v.v.) bằng cách gọi libm chức năng. Nhìn vào các thay đổi glibc, chúng tôi tìm thấy một số tối ưu hóa trong các hàm lượng giác:đối với một số đầu vào nhất định, các phép tính lượng giác sử dụng các phím tắt không thể sử dụng cho các đầu vào khác; và các phím tắt như vậy đã được tối ưu hóa theo thời gian. Thật vậy, glibc thông báo cho cả 2,27 và 2,29 đều đề cập đến việc tối ưu hóa trong các hàm sin / cosine / etc. Rõ ràng, đã từng có một số tối ưu hóa của Intel được cho là cung cấp kết quả rất chính xác, nhưng sau đó ai đó nhận ra rằng tuyên bố về độ chính xác là không chính xác, vì vậy glibc đã vô hiệu hóa việc sử dụng các tối ưu hóa đó; sau đó, công cụ đó đã được thực hiện lại theo một cách khác nhưng nhanh chóng. Hoặc những thứ tương tự - đối với những người ngoài cuộc như tôi, thật khó để tìm ra chi tiết chính xác.

Chúng tôi nghi ngờ rằng việc nâng cấp lên phiên bản glibc mới hơn sẽ khắc phục được sự cố, khiến mọi thứ khác như cũ. Khách hàng của chúng tôi đã thử điều đó, và thực sự là đúng, và họ rất vui. Chúng tôi không thực sự chắc chắn cái nào những thay đổi glibc này phải chịu trách nhiệm, nhưng có một điều rõ ràng là chạy mọi thứ trên phần mềm cập nhật luôn là một ý kiến ​​hay.

Hãy nhớ rằng các cạnh chảy máu rất sắc… vì vậy hãy cẩn thận khi ở bên ngoài.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kiểm tra xem NULL có tồn tại trong mảng Postgres không

  2. Cách sao lưu và khôi phục cơ sở dữ liệu PostgreSQL

  3. Các ký tự tối đa trong nhãn (tên bảng, cột, v.v.)

  4. Cách tạo người dùng với PSQL

  5. Cách cbrt () hoạt động trong PostgreSQL