收集分区统计信息

ANALYZE_STATISTICS_PARTITION 收集和聚合指定表中一系列分区的数据样本和存储信息。Vertica 将收集的统计信息写入数据库编录。

例如,下表存储销售数据并按订单日期进行分区:

CREATE TABLE public.store_orders_fact
(
    product_key int,
    product_version int,
    store_key int,
    vendor_key int,
    employee_key int,
    order_number int,
    date_ordered date NOT NULL,
    date_shipped date NOT NULL,
    quantity_ordered int,
    shipper_name varchar(32)
);

ALTER TABLE public.store_orders_fact PARTITION BY date_ordered::DATE GROUP BY CALENDAR_HIERARCHY_DAY(date_ordered::DATE, 2, 2) REORGANIZE;
ALTER TABLE public.store_orders_fact ADD CONSTRAINT fk_store_orders_product FOREIGN KEY (product_key, product_version) references public.product_dimension (product_key, product_version);
ALTER TABLE public.store_orders_fact ADD CONSTRAINT fk_store_orders_vendor FOREIGN KEY (vendor_key) references public.vendor_dimension (vendor_key);
ALTER TABLE public.store_orders_fact ADD CONSTRAINT fk_store_orders_employee FOREIGN KEY (employee_key) references public.employee_dimension (employee_key);

在每个工作日结束时,您可能会调用 ANALYZE_STATISTICS_PARTITION 并收集有关最新(今天)分区的所有数据的统计信息:

=> SELECT ANALYZE_STATISTICS_PARTITION('public.store_orders_fact', CURRENT_DATE::VARCHAR(10), CURRENT_DATE::VARCHAR(10));
 ANALYZE_STATISTICS_PARTITION
------------------------------
                            0
(1 row)

该函数为 store.store_sales_fact 中的最新分区生成一组新统计信息。如果您每天早上查询这张表昨天的销售额,优化器会使用这些统计信息来生成优化的查询计划:

=> EXPLAIN SELECT COUNT(*) FROM public.store_orders_fact WHERE date_ordered = CURRENT_DATE-1;

                                           QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 QUERY PLAN DESCRIPTION:
 ------------------------------

 EXPLAIN SELECT COUNT(*) FROM public.store_orders_fact WHERE date_ordered = CURRENT_DATE-1;

 Access Path:
 +-GROUPBY NOTHING [Cost: 2, Rows: 1] (PATH ID: 1)
 |  Aggregates: count(*)
 |  Execute on: All Nodes
 | +---> STORAGE ACCESS for store_orders_fact [Cost: 1, Rows: 222(PARTITION-LEVEL STATISTICS)] (PATH ID: 2)
 | |      Projection: public.store_orders_fact_v1_b1
 | |      Filter: (store_orders_fact.date_ordered = '2019-04-01'::date)
 | |      Execute on: All Nodes

缩小收集范围

ANALYZE_STATISTICS 一样,ANALYZE_STATISTICS_PARTITION 允许您将分析范围缩小到 表列的子集。您还可以控制它收集的数据样本的大小。有关这些选项的详细信息,请参阅收集表统计信息

收集多个分区范围的统计信息

如果指定多个分区,它们必须是连续的分区。不同的统计数据集合可以重叠。例如,下表 t1 在列 c1 中已分区:

=> SELECT export_tables('','t1');
                                          export_tables
-------------------------------------------------------------------------------------------------
CREATE TABLE public.t1
(
    a int,
    b int,
    c1 int NOT NULL
)
PARTITION BY (t1.c1);


=> SELECT * FROM t1 ORDER BY c1;
 a  | b  | c1
----+----+----
  1 |  2 |  3
  4 |  5 |  6
  7 |  8 |  9
 10 | 11 | 12
(4 rows)

对于此数据集,您可以在 t1 上调用 ANALYZE_STATISTICS_PARTITION 两次。连续调用会收集分区键的两个重叠范围(3 到 9 和 6 到 12)的统计信息:

=> SELECT drop_statistics_partition('t1', '', '');
 drop_statistics_partition
---------------------------
                         0
(1 row)

=> SELECT analyze_statistics_partition('t1', '3', '9');
 analyze_statistics_partition
------------------------------
                            0
(1 row)

=> SELECT analyze_statistics_partition('t1', '6', '12');
 analyze_statistics_partition
------------------------------
                            0
(1 row)

=> SELECT table_name, min_partition_key, max_partition_key, row_count FROM table_statistics WHERE table_name = 't1';
 table_name | min_partition_key | max_partition_key | row_count
------------+-------------------+-------------------+-----------
 t1         | 3                 | 9                 |         3
 t1         | 6                 | 12                |         3
(2 rows)

如果两个统计信息集合重叠,Vertica 仅存储每个分区范围的最新统计信息。因此,在上一个示例中,Vertica 仅使用来自第二个集合的分区键 6 到 9 的统计信息。

为给定分区键范围收集的统计信息始终取代先前为该范围的子集收集的统计信息。例如,假设 ANALYZE_STATISTICS_PARTITION 调用指定了分区键 3 到 12,则收集的统计信息是之前收集的两组统计信息的超集,因此它将取代两者:


=> SELECT analyze_statistics_partition('t1', '3', '12');
 analyze_statistics_partition
------------------------------
                            0
(1 row)

=> SELECT table_name, min_partition_key, max_partition_key, row_count FROM table_statistics WHERE table_name = 't1';
 table_name | min_partition_key | max_partition_key | row_count
------------+-------------------+-------------------+-----------
 t1         | 3                 | 12                |         4
(1 row)

最后,ANALYZE_STATISTICS_PARTITION 收集分区键 3 到 6 的统计信息。此集合是上一个集合的子集,因此 Vertica 将保留这两个集合,并使用每个集合的最新统计信息:


=> SELECT analyze_statistics_partition('t1', '3', '6');
 analyze_statistics_partition
------------------------------
                            0
(1 row)

=> SELECT table_name, min_partition_key, max_partition_key, row_count FROM table_statistics WHERE table_name = 't1';
 table_name | min_partition_key | max_partition_key | row_count
------------+-------------------+-------------------+-----------
 t1         | 3                 | 12                |         4
 t1         | 3                 | 6                 |         2
(2 rows)

受支持的日期/时间函数

ANALYZE_STATISTICS_PARTITION 可以在分区表达式已指定以下日期/时间函数之一的表中收集分区级统计信息:

要求和限制

ANALYZE_STATISTICS_PARTITION 具有以下要求和限制:

  • 该表必须进行分区,并且不能包含未分区的数据。

  • 表分区表达式必须指定单个列。支持以下表达式:

    • 仅指定列的表达式,即对所有列值进行分区。例如:

      PARTITION BY ship_date GROUP BY CALENDAR_HIERARCHY_DAY(ship_date, 2, 2)
      
    • 如果列是 DATETIMESTAMP/TIMESTAMPTZ,则分区表达式可以指定支持的日期/时间函数,该函数会返回该列或其任何部分,例如月份或年份。例如,以下分区表达式指定对列 order_date 的年份部分进行分区:

      PARTITION BY YEAR(order_date)
      
    • 该表达式对列执行加法或减法。例如:

      PARTITION BY YEAR(order_date) -1
      
  • 表分区表达式不能将指定列强制转换为另一种数据类型。

  • Vertica 不从以下投影中收集任何统计数据:

    • 实时聚合投影和 Top-K 投影

    • 定义这些投影可以在表达式中包含 SQL 函数