提高查询性能(仅限 C++)
评估查询时,Vertica 优化器可能会对其输入进行排序以提高性能。如果函数已返回排序后的数据,这意味着优化器正在执行额外的工作。使用 C++ 语言编写的转换函数可以声明其返回的数据的排序方式,这样优化器就可以利用这些信息。
转换函数会在函数的 processPartition()
方法中进行实际排序。要利用这种优化,排序必须为升序。您不需要对所有列进行排序,但必须先返回已排序的列。
您可以在工厂的 getReturnType()
方法中声明函数对其输出进行排序的方式。
当心
如果工厂中声明的排序与函数提供的排序不匹配,则查询结果可能不正确。PolyTopKPerPartition
示例会对输入列进行排序并返回给定的行数:
=> SELECT polykSort(14, a, b, c) OVER (ORDER BY a, b, c)
AS (sort1,sort2,sort3) FROM observations ORDER BY 1,2,3;
sort1 | sort2 | sort3
-------+-------+-------
1 | 1 | 1
1 | 1 | 2
1 | 1 | 3
1 | 2 | 1
1 | 2 | 2
1 | 3 | 1
1 | 3 | 2
1 | 3 | 3
1 | 3 | 4
2 | 1 | 1
2 | 1 | 2
2 | 2 | 3
2 | 2 | 34
2 | 3 | 5
(14 rows)
工厂会通过在每一列上设置 isSortedBy
属性在 getReturnType()
中声明此排序。每个 SizedColumnType
都存在关联的 Properties
对象,您可以在其中设置此值:
virtual void getReturnType(ServerInterface &srvInterface, const SizedColumnTypes &inputTypes, SizedColumnTypes &outputTypes)
{
vector<size_t> argCols; // Argument column indexes.
inputTypes.getArgumentColumns(argCols);
size_t colIdx = 0;
for (vector<size_t>::iterator i = argCols.begin() + 1; i < argCols.end(); i++)
{
SizedColumnTypes::Properties props;
props.isSortedBy = true;
std::stringstream cname;
cname << "col" << colIdx++;
outputTypes.addArg(inputTypes.getColumnType(*i), cname.str(), props);
}
}
通过查看包含和不包含此设置的查询的 EXPLAIN 计划,可以查看此优化的效果。以下输出显示了 polyk
(未排序的版本)的查询计划。记录排序成本:
=> EXPLAN SELECT polyk(14, a, b, c) OVER (ORDER BY a, b, c)
FROM observations ORDER BY 1,2,3;
Access Path:
+-SORT [Cost: 2K, Rows: 10K] (PATH ID: 1)
| Order: col0 ASC, col1 ASC, col2 ASC
| +---> ANALYTICAL [Cost: 2K, Rows: 10K] (PATH ID: 2)
| | Analytic Group
| | Functions: polyk()
| | Group Sort: observations.a ASC NULLS LAST, observations.b ASC NULLS LAST, observations.c ASC NULLS LAST
| | +---> STORAGE ACCESS for observations [Cost: 2K, Rows: 10K]
(PATH ID: 3)
| | | Projection: public.observations_super
| | | Materialize: observations.a, observations.b, observations.c
已排序版本的查询计划会忽略此步骤(从而节省成本)并从分析步骤开始(上一个计划中的第二个步骤):
=> EXPLAN SELECT polykSort(14, a, b, c) OVER (ORDER BY a, b, c)
FROM observations ORDER BY 1,2,3;
Access Path:
+-ANALYTICAL [Cost: 2K, Rows: 10K] (PATH ID: 2)
| Analytic Group
| Functions: polykSort()
| Group Sort: observations.a ASC NULLS LAST, observations.b ASC NULLS LAST, observations.c ASC NULLS LAST
| +---> STORAGE ACCESS for observations [Cost: 2K, Rows: 10K] (PATH ID: 3)
| | Projection: public.observations_super
| | Materialize: observations.a, observations.b, observations.c