具有谓词的查询的投影

如果查询包含一个或多个谓词,您可以修改投影来提升查询的性能,如以下两个示例所述。

使用日期范围的查询

此示例显示了如何使用 RLE 对数据进行编码,以及更改投影排序顺序以提升检索给定日期范围内所有数据的查询的性能。

假设您的查询类似于如下内容:

=> SELECT * FROM trades
   WHERE trade_date BETWEEN '2016-11-01' AND '2016-12-01';

要优化此查询,请确定所有投影是否可以及时执行 SELECT 操作。为每个投影运行指定了日期范围的 SELECT COUNT(*) 语句,并记下响应时间。例如:

=> SELECT COUNT(*) FROM [ projection_name ]
   WHERE trade_date BETWEEN '2016-11-01' AND '2016-12-01;

如果一个或多个查询很慢,请检查 trade_date 列的唯一性,并确定它是否需要位于投影的 ORDER BY 子句中和/或是否可以使用 RLE 进行编码。RLE 会将列中的相同数据值的序列替换为代表值和计数的配对。要获得最佳效果,请从最低基数到最高基数对投影中的列进行排序,并使用 RLE 对低基数列中的数据进行编码。

如果唯一列的数量未经过排序,或者重复行的平均数量小于 10,那么 trade_date 会因为太过于接近而难以变成唯一,而且不能使用 RLE 进行编码。在这种情况下,请添加新列以最大程度缩小搜索范围。

以下示例会添加一个新列 trade_year

  1. 确定新列 trade_year 是否返回了可管理的结果集。以下查询返回了按 trade_year 进行分组的数据:

    => SELECT DATE_TRUNC('trade_year', trade_date), COUNT(*)
       FROM trades
       GROUP BY DATE_TRUNC('trade_year',trade_date);
    
  2. 假设 trade_year = 2007 接近 8k,请将 trade_year 的列添加到 trades 表。然后,SELECT 语句就会变为:

    => SELECT * FROM trades
       WHERE trade_year = 2007
       AND trade_date BETWEEN '2016-11-01' AND '2016-12-01';
    

    因此,您会具有对 trade_year 进行排序的投影,而且它可以使用 RLE 进行编码。

具有高基数主键的表的查询

此示例说明了您可以如何修改投影来提升从具有高基数主键的表中选择数据的查询的性能。

假设您有这样的一个查询:

=> SELECT FROM [table]
   WHERE pk IN (12345, 12346, 12347,...);

由于主键是高基数列,因此 Vertica 必须搜索大量数据。

要优化此查询的架构,请创建名为 buckets 的新列,并向其分配主键除以 10000 的值。在此示例中,buckets=(int) pk/10000。请按如下所示使用 buckets 列限制搜索范围:

=> SELECT FROM [table]
   WHERE buckets IN (1,...)
   AND pk IN (12345, 12346, 12347,...);

创建较低基数的列并将其添加到查询会限制搜索范围并提升查询性能。此外,如果您创建 buckets 在排序顺序中位于第一位的投影,查询可能会运行地更快。