Thống kê về chỉ mục trên các phân vùng không được sử dụng trong truy vấn trên toàn bộ bảng


9

Phép nối sau đây có các ước tính hàng rất khác nhau khi thực hiện phép nối trên các phân vùng so với khi tham gia trên toàn bộ bảng:

CREATE TABLE m_data.ga_session (
  session_id         BIGINT                   NOT NULL,
  visitor_id         BIGINT                   NOT NULL,
  transaction_id     TEXT,

  timestamp          TIMESTAMP WITH TIME ZONE NOT NULL,
  day_id             INTEGER                  NOT NULL,
  [...]

  device_category    TEXT                     NOT NULL,
  [...]
  operating_system   TEXT

);

Đối với tất cả các phân vùng:

CREATE TABLE IF NOT EXISTS m_data.ga_session_20170127 ( CHECK (day_id = 20170127) ) INHERITS (m_data.ga_session);
-- the identifier are theoretically invalid, but they get truncated to 63 chars and nevertheless work
CREATE INDEX IF NOT EXISTS "ga_session__m_tmp.normalize_device_category(ga_session.device_category)" on m_data.ga_session_20170127 USING btree (m_tmp.normalize_device_category(device_category)) ;
CREATE INDEX IF NOT EXISTS "ga_session__m_tmp.normalize_operating_system(operating_system)" on m_data.ga_session_20170127 USING btree (m_tmp.normalize_operating_system(operating_system)) ;
ANALYZE m_data.ga_session_20170127;

EXPLAIN analyse
SELECT * 
  FROM m_data.ga_session_20170127 ga_session
    JOIN m_dim_next.device ON 
      device.device_category_name = m_tmp.normalize_device_category(ga_session.device_category)
      AND device.operating_system_name = m_tmp.normalize_operating_system(ga_session.operating_system);

Số liệu thống kê cho các chỉ mục này trên các phân vùng có thể nhìn thấy:

SELECT * FROM pg_stats WHERE tablename ilike 'ga_session_20170127%';

schemaname |tablename                                                       |attname                    |inherited |null_frac   |avg_width |n_distinct   
-----------|----------------------------------------------------------------|---------------------------|----------|------------|----------|-------------
m_data     |ga_session_20170127__m_tmp.normalize_device_category(device_cat |normalize_device_category  |false     |0           |10        |3            
m_data     |ga_session_20170127__m_tmp.normalize_operating_system(operating |normalize_operating_system |false     |0           |7         |14           

Điều này (với số liệu thống kê về chỉ mục trên phân vùng) dẫn đến các ước tính kế hoạch truy vấn (tiền phạt) sau: ước tính 80146, thực tế 77503

Hash Join  (cost=1.95..6103.53 rows=80146 width=262) (actual time=0.121..117.204 rows=77503 loops=1)
  Hash Cond: ((COALESCE(initcap(ga_session.device_category), 'Unknown'::text) = device.device_category_name) AND (COALESCE(replace(ga_session.operating_system, '(not set)'::text, 'Unknown'::text), 'Unknown'::text) = device.operating_system_name))
  ->  Seq Scan on ga_session_20170127 ga_session  (cost=0.00..2975.03 rows=77503 width=224) (actual time=0.010..9.203 rows=77503 loops=1)
  ->  Hash  (cost=1.38..1.38 rows=38 width=38) (actual time=0.064..0.064 rows=38 loops=1)
        Buckets: 1024  Batches: 1  Memory Usage: 11kB
        ->  Seq Scan on device  (cost=0.00..1.38 rows=38 width=38) (actual time=0.006..0.019 rows=38 loops=1)
Planning time: 1.460 ms
Execution time: 120.098 ms

Điều không hiệu quả là tham gia trên toàn bộ bảng, ước tính số hàng hoàn toàn sai (832 ước tính so với 876237 thực tế).

QUERY PLAN                                                                                                                                                                                                                                             
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Hash Join  (cost=1.95..60056.78 rows=832 width=262) (actual time=0.037..1065.778 rows=876237 loops=1)                                                                                                                                                  
  Hash Cond: ((COALESCE(initcap(ga_session.device_category), 'Unknown'::text) = device.device_category_name) AND (COALESCE(replace(ga_session.operating_system, '(not set)'::text, 'Unknown'::text), 'Unknown'::text) = device.operating_system_name)) 
  ->  Append  (cost=0.00..33759.37 rows=876238 width=225) (actual time=0.005..132.070 rows=876237 loops=1)                                                                                                                                             
        ->  Seq Scan on ga_session  (cost=0.00..0.00 rows=1 width=319) (actual time=0.000..0.000 rows=0 loops=1)                                                                                                                                       
        ->  Seq Scan on ga_session_20170125 ga_session_1  (cost=0.00..3648.38 rows=94438 width=226) (actual time=0.005..10.606 rows=94438 loops=1)                                                                                                     
        ->  Seq Scan on ga_session_20170126 ga_session_2  (cost=0.00..3185.81 rows=82581 width=225) (actual time=0.014..8.982 rows=82581 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170127 ga_session_3  (cost=0.00..2975.03 rows=77503 width=224) (actual time=0.002..8.797 rows=77503 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170128 ga_session_4  (cost=0.00..2936.83 rows=76083 width=225) (actual time=0.003..7.873 rows=76083 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170129 ga_session_5  (cost=0.00..3716.18 rows=96618 width=224) (actual time=0.002..9.318 rows=96618 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170130 ga_session_6  (cost=0.00..3833.19 rows=99619 width=224) (actual time=0.002..9.453 rows=99619 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170131 ga_session_7  (cost=0.00..3488.79 rows=90579 width=225) (actual time=0.002..8.298 rows=90579 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170201 ga_session_8  (cost=0.00..3615.58 rows=93958 width=224) (actual time=0.002..9.199 rows=93958 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170202 ga_session_9  (cost=0.00..3286.56 rows=85256 width=224) (actual time=0.006..8.021 rows=85256 loops=1)                                                                                                      
        ->  Seq Scan on ga_session_20170203 ga_session_10  (cost=0.00..3073.02 rows=79602 width=225) (actual time=0.002..7.727 rows=79602 loops=1)                                                                                                     
  ->  Hash  (cost=1.38..1.38 rows=38 width=38) (actual time=0.016..0.016 rows=38 loops=1)                                                                                                                                                              
        Buckets: 1024  Batches: 1  Memory Usage: 11kB                                                                                                                                                                                                  
        ->  Seq Scan on device  (cost=0.00..1.38 rows=38 width=38) (actual time=0.002..0.004 rows=38 loops=1)                                                                                                                                          
Planning time: 1.017 ms                                                                                                                                                                                                                                
Execution time: 1090.213 ms   

Điều này sau đó lần lượt dẫn đến các lựa chọn tham gia sai (các vòng lặp lồng nhau) khi sử dụng kết quả tham gia đó trong nhiều kết nối hơn (không được hiển thị ở đây).

Tôi thực sự đã ước tính hàng sai trên các phân vùng cũng như trước khi tôi chạy ANALYSElại trên các phân vùng, vì vậy có vẻ như trình hoạch định truy vấn không tính đến các thống kê dựa trên chỉ mục khi sử dụng toàn bộ bảng.

Có cách nào để làm cho trình lập kế hoạch truy vấn thu thập số liệu thống kê về cấp độ của bảng cha hoặc lấy số liệu thống kê riêng của các phân vùng khi xây dựng kế hoạch truy vấn không?


2
Câu hỏi sẽ hoạt động tốt hơn đối với tôi nếu bạn cung cấp (các phần có liên quan) định nghĩa bảng và chỉ mục thực tế của bạn. Làm thế nào bạn thực hiện các phân vùng? Với thừa kế? Sau đó, không có thứ gọi là "chỉ mục được tạo trên toàn bộ bảng" Mỗi chỉ mục chỉ có thể trải rộng trên một bảng vật lý, tức là một phân vùng duy nhất.
Erwin Brandstetter

Xin lỗi, tôi đã thêm thông tin. Các chỉ mục nằm trên mỗi bảng (Tôi đã nhầm lẫn khi chúng ta chỉ gọi một hàm để tạo chỉ mục trên tất cả các bảng kế thừa).
Jan Katins

Câu trả lời:


1

Hãy chắc chắn rằng không chỉ các phân vùng được lập chỉ mục, mà cả bảng chính cũng được lập chỉ mục theo cùng một cách và ANALYZEd.

Điều này có thể làm cho trình lập kế hoạch bao gồm các ước tính dựa trên chỉ mục trên một phân vùng duy nhất, nhưng bỏ qua chúng ở cấp bảng chính.

Nếu chỉ số biểu thức hoặc số liệu thống kê cho bảng chính bị thiếu, trình hoạch định không thể suy ra tham gia cardinality từ điều kiện này - ngay cả khi nó có số liệu thống kê hoàn hảo cho các phân vùng.

Đó chỉ là dự đoán vì bạn không cung cấp lược đồ đầy đủ. Xin vui lòng cho tôi biết nếu điều này giúp.

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.