提交 eadc5276 编写于 作者: V Venkatesh Raghavan 提交者: Omer Arap

Pass the array size to GPORCA when do array comparion

When the size of the array is more than `100` our translator does not expand the arrays.
This make GPORCA's cardinality estimation model think it is an unsupported predicate
which in turn makes it the cardinality wrong:

```
create table foo(a int, b int);
insert into foo select i, i from generate_series(1,100) i;
```

Next force GPORCA to not expand the array

```
vraghavan=# set optimizer_array_expansion_threshold = 1;
SET
vraghavan=# explain select * from foo where b in (1, 2, 3);                                                                                                                                                                                                                                                                                                                                           QUERY PLAN
-------------------------------------------------------------------------------
 Gather Motion 3:1  (slice1; segments: 3)  (cost=0.00..431.00 rows=40 width=8)
   ->  Table Scan on foo  (cost=0.00..431.00 rows=14 width=8)
         Filter: b = ANY ('{1,2,3}'::integer[])
 Settings:  optimizer_array_expansion_threshold=1
 Optimizer status: PQO version 2.75.0
(5 rows)
```

In the example,:

* Table has 100 rows
* Each column has unique value for b
* Array of the in clause has 3 values. So cardinality must be at most 3.
* Since the array is not expanded we get wrong cardinality estimation

In this change, we pass the size of the array constant so that GPORCA can try do a
better job estimating cardinality.

Associated GPORCA PR: https://github.com/greenplum-db/gporca/pull/405
上级 be7a4e12
......@@ -2966,12 +2966,13 @@ gpdb::DefGetString
Expr *
gpdb::TransformArrayConstToArrayExpr
(
Const *c
Const *c,
int *arrayLen
)
{
GP_WRAP_START;
{
return transform_array_Const_to_ArrayExpr(c);
return transform_array_Const_to_ArrayExpr(c, arrayLen);
}
GP_WRAP_END;
return NULL;
......
......@@ -514,12 +514,13 @@ CTranslatorScalarToDXL::CreateScalarArrayCompFromExpr
Expr *right_expr = (Expr*) gpdb::ListNth(scalar_array_op_expr->args, 1);
int arrayLen = 0;
// If the argument array is an array Const, try to transform it to an
// ArrayExpr, to allow ORCA to optimize it better. (ORCA knows how to
// extract elements of an ArrayExpr, but doesn't currently know how
// to do it from an array-typed Const.)
if (IsA(right_expr, Const))
right_expr = gpdb::TransformArrayConstToArrayExpr((Const *) right_expr);
right_expr = gpdb::TransformArrayConstToArrayExpr((Const *) right_expr, &arrayLen);
CDXLNode *right_node = TranslateScalarToDXL(right_expr, var_colid_mapping);
......@@ -541,7 +542,14 @@ CTranslatorScalarToDXL::CreateScalarArrayCompFromExpr
type = Edxlarraycomptypeall;
}
CDXLScalarArrayComp *dxlop = GPOS_NEW(m_mp) CDXLScalarArrayComp(m_mp, GPOS_NEW(m_mp) CMDIdGPDB(scalar_array_op_expr->opno), GPOS_NEW(m_mp) CWStringConst(op_name->GetBuffer()), type);
CDXLScalarArrayComp *dxlop = GPOS_NEW(m_mp) CDXLScalarArrayComp
(
m_mp,
GPOS_NEW(m_mp) CMDIdGPDB(scalar_array_op_expr->opno),
GPOS_NEW(m_mp) CWStringConst(op_name->GetBuffer()),
type,
arrayLen
);
// create the DXL node holding the scalar opexpr
CDXLNode *dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, dxlop);
......
......@@ -2370,7 +2370,7 @@ fold_constants(PlannerInfo *root, Query *q, ParamListInfo boundParams, Size max_
* large arrays.
*/
Expr *
transform_array_Const_to_ArrayExpr(Const *c)
transform_array_Const_to_ArrayExpr(Const *c, int *arrayLen)
{
Oid elemtype;
int16 elemlen;
......@@ -2395,6 +2395,7 @@ transform_array_Const_to_ArrayExpr(Const *c)
ac = DatumGetArrayTypeP(c->constvalue);
nelems = ArrayGetNItems(ARR_NDIM(ac), ARR_DIMS(ac));
*arrayLen = nelems;
/* All set, extract the elements, and an ArrayExpr to hold them. */
get_typlenbyvalalign(elemtype, &elemlen, &elembyval, &elemalign);
......
......@@ -624,7 +624,7 @@ namespace gpdb {
char *DefGetString(DefElem *defelem);
// transform array Const to an ArrayExpr
Expr *TransformArrayConstToArrayExpr(Const *constant);
Expr *TransformArrayConstToArrayExpr(Const *constant, int *arrayLen);
// transform array Const to an ArrayExpr
Node *EvalConstExpressions(Node *node);
......
......@@ -108,7 +108,7 @@ extern Node *eval_const_expressions(PlannerInfo *root, Node *node);
extern Query *fold_constants(PlannerInfo *root, Query *q, ParamListInfo boundParams, Size max_size);
extern Expr *transform_array_Const_to_ArrayExpr(Const *c);
extern Expr *transform_array_Const_to_ArrayExpr(Const *c, int *);
extern Node *estimate_expression_value(PlannerInfo *root, Node *node);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册