2017-09-10 20 views
11

Chạy PostgreSQL 9.6.4 trên máy tính xách tay của tôi, tôi có một bảng có tên là node có khóa chính là id và trường properties::jsonb.Tối ưu hóa truy vấn khi sử dụng trường JSON

Tôi có thiết lập chỉ mục GIN trên trường properties.

Khi tôi chạy truy vấn này:

SELECT n.* 
FROM  node n 
WHERE node_type_id = '2' 
AND  properties @> '{"slug":"wild-castles"}'::JSONB 
ORDER BY n.id ASC OFFSET 0 LIMIT 10; 

trên ~ 5M bảng hàng phải mất khoảng 20 giây để có được một câu trả lời. Nhìn vào kế hoạch giải thích tôi phát hiện ra tôi ưu truy vấn là lần đầu tiên sắp xếp bảng theo khóa chính và sau đó lọc theo các properties lĩnh vực:

Limit (cost=0.56..1517.94 rows=10 width=154) 
    -> Index Scan using node_pkey on node n (cost=0.56..739571.11 rows=4874 width=154) 
     Filter: ((properties @> '{"slug": "wild-castles"}'::jsonb) AND ((node_type_id)::text = '2'::text)) 

Nhưng khi tôi loại bỏ các đặt hàng tôi nhìn thấy tôi ưu hoa bằng cách sử dụng chỉ số như mong đợi:

SELECT n.* 
FROM node n 
WHERE node_type_id = '2' 
AND properties @> '{"slug":"wild-castles"}'::JSONB 
OFFSET 0 LIMIT 10; 

Limit (cost=93.77..127.10 rows=10 width=154) 
    -> Bitmap Heap Scan on node n (cost=93.77..16338.56 rows=4874 width=154) 
     Recheck Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 
     Filter: ((node_type_id)::text = '2'::text) 
     -> Bitmap Index Scan on node_ix02 (cost=0.00..92.55 rows=4874 width=0) 
       Index Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 

Ngoài ra, một đơn giản WHERE properties @> '{"slug":"wild-castles"}'::JSONB cư xử như mong đợi:

EXPLAIN SELECT n.* 
FROM  node n 
WHERE properties @> '{"slug":"wild-castles"}'::JSONB 
; 

Bitmap Heap Scan on node n (cost=93.77..16326.38 rows=4874 width=154) 
    Recheck Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 
    -> Bitmap Index Scan on node_ix02 (cost=0.00..92.55 rows=4874 width=0) 
     Index Cond: (properties @> '{"slug": "wild-castles"}'::jsonb) 

vì vậy, tôi đoán tôi đang tự hỏi tại sao wo uld trình tối ưu hóa không sử dụng chỉ mục để lọc ra các hàng đầu tiên và sau đó sắp xếp chúng theo trường id?

+0

Các ước tính cho một đơn giản 'nơi các thuộc tính @> '{" slug ":" wild-castles "}' :: JSONB' là gì? – teppic

+0

Tôi đã cập nhật câu hỏi. – acohen

+0

Phần trăm nút nào có trường "slug"? Phần trăm của các nút đó có thuộc tính "slug" với giá trị "wild-castles". – teppic

Trả lời

1

Thay đổi Planner Method Configuration và lực lượng planer không làm seqscan

ví dụ

 SET enable_seqscan = OFF; 

     SELECT n.* 
     FROM  node n 
       WHERE node_type_id = '2' 
       AND  properties @> '{"slug":"wild-castles"}'::JSONB 
      ORDER BY n.id ASC OFFSET 0 LIMIT 10; 
1

Theo kinh nghiệm của tôi, đôi khi bạn phải đánh lừa các nhà quy hoạch truy vấn để làm cho nó thực hiện tốt, và phải mất một số tinh chỉnh và loay hoay với ...

tôi sẽ cố gắng chạy này để xem cách nó thực hiện:

SELECT nn.* FROM (
    SELECT n.* 
    FROM node n 
    WHERE node_type_id = '2' 
    AND properties @> '{"slug":"wild-castles"}'::JSONB 
) nn 
ORDER BY nn.id ASC OFFSET 0 LIMIT 10; 
Các vấn đề liên quan