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

Chỉ mục postgresql trên biểu thức xpath không tăng tốc độ

Chà, ít nhất chỉ mục được sử dụng. Tuy nhiên, bạn nhận được một bản quét chỉ mục bitmap thay vì quét chỉ mục bình thường, có nghĩa là hàm xpath () sẽ được gọi rất nhiều lần.

Hãy kiểm tra một chút:

CREATE TABLE foo ( id serial primary key, x xml, h hstore );
insert into foo (x,h) select XMLPARSE( CONTENT '<row  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
   <object_id>2</object_id>  
   <pack_form_id>' || n || '</pack_form_id>  
   <prod_form_id>34</prod_form_id>
 </row>' ), 
('object_id=>2,prod_form_id=>34,pack_form_id=>'||n)::hstore 
FROM generate_series( 1,100000 ) n;

test=> EXPLAIN ANALYZE SELECT count(*) FROM foo;
                                                   QUERY PLAN                                                    
-----------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=4821.00..4821.01 rows=1 width=0) (actual time=24.694..24.694 rows=1 loops=1)
   ->  Seq Scan on foo  (cost=0.00..4571.00 rows=100000 width=0) (actual time=0.006..13.996 rows=100000 loops=1)
 Total runtime: 24.730 ms

test=> explain analyze select * from foo where (h->'pack_form_id')='123';
                                             QUERY PLAN                                             
----------------------------------------------------------------------------------------------------
 Seq Scan on foo  (cost=0.00..5571.00 rows=500 width=68) (actual time=0.075..48.763 rows=1 loops=1)
   Filter: ((h -> 'pack_form_id'::text) = '123'::text)
 Total runtime: 36.808 ms

test=> explain analyze select * from foo where ((xpath('//pack_form_id/text()'::text, x))[1]::text) = '123';
                                              QUERY PLAN                                              
------------------------------------------------------------------------------------------------------
 Seq Scan on foo  (cost=0.00..5071.00 rows=500 width=68) (actual time=4.271..3368.838 rows=1 loops=1)
   Filter: (((xpath('//pack_form_id/text()'::text, x, '{}'::text[]))[1])::text = '123'::text)
 Total runtime: 3368.865 ms

Như chúng ta có thể thấy,

  • quét toàn bộ bảng với số đếm (*) mất 25 mili giây
  • trích xuất một khóa / giá trị từ một hstore sẽ làm tăng thêm một khoản chi phí nhỏ, khoảng 0,12 µs / hàng
  • trích xuất một khóa / giá trị từ xml bằng xpath sẽ làm tăng thêm chi phí, khoảng 33 µs / hàng

Kết luận:

  • xml chậm (nhưng mọi người đều biết điều đó)
  • nếu bạn muốn đặt kho khóa / giá trị linh hoạt trong một cột, hãy sử dụng hstore

Ngoài ra, vì dữ liệu xml của bạn khá lớn nên nó sẽ được nướng (nén và lưu trữ ngoài bảng chính). Điều này làm cho các hàng trong bảng chính nhỏ hơn nhiều, do đó nhiều hàng hơn trên mỗi trang, điều này làm giảm hiệu quả của việc quét bitmap vì tất cả các hàng trên một trang phải được kiểm tra lại.

Bạn có thể sửa lỗi này. Vì lý do nào đó, hàm xpath () (rất chậm, vì nó xử lý xml) có cùng chi phí (1 đơn vị) như toán tử số nguyên "+" ...

update pg_proc set procost=1000 where proname='xpath';

Bạn có thể cần phải điều chỉnh giá trị chi phí. Khi được cung cấp thông tin phù hợp, người lập kế hoạch biết xpath chậm và sẽ tránh quét chỉ mục bitmap, thay vào đó sử dụng quét chỉ mục, không cần kiểm tra lại điều kiện cho tất cả các hàng trên trang.

Lưu ý rằng điều này không giải quyết vấn đề ước tính hàng. Vì bạn không thể PHÂN TÍCH bên trong xml (hoặc hstore), bạn sẽ nhận được ước tính mặc định cho số hàng (ở đây, 500). Vì vậy, người lập kế hoạch có thể hoàn toàn sai lầm và chọn một kế hoạch thảm khốc nếu có sự tham gia của một số người. Giải pháp duy nhất cho điều này là sử dụng các cột thích hợp.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres UPDATE to_tsvector cập nhật tất cả các hàng thành cùng một giá trị

  2. psql:không thể kết nối với máy chủ:Không có tệp hoặc thư mục như vậy (Mac OS X)

  3. cách phân tích cú pháp json bằng json_populate_recordset trong postgres

  4. Dấu thời gian loại thay đổi PostgreSQL không có múi giờ -> có múi giờ

  5. Các biến môi trường docker-compile