patch 4.0
This commit is contained in:
@ -12,67 +12,58 @@
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "sql/engine/expr/ob_expr_estimate_ndv.h"
|
||||
|
||||
constexpr double DOUBLE_OVERFLOW_UINT64 = static_cast<double>(UINT64_MAX);
|
||||
#include "sql/engine/aggregate/ob_aggregate_processor.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
|
||||
namespace oceanbase {
|
||||
namespace sql {
|
||||
ObExprEstimateNdv::ObExprEstimateNdv(ObIAllocator& alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_ESTIMATE_NDV, "estimate_ndv", 1, NOT_ROW_DIMENSION)
|
||||
{}
|
||||
ObExprEstimateNdv::ObExprEstimateNdv(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_ESTIMATE_NDV, "estimate_ndv", 1, NOT_ROW_DIMENSION,
|
||||
INTERNAL_IN_MYSQL_MODE, INTERNAL_IN_ORACLE_MODE)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprEstimateNdv::~ObExprEstimateNdv()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprEstimateNdv::calc_result_type1(ObExprResType& type, ObExprResType& type1, ObExprTypeCtx& type_ctx) const
|
||||
int ObExprEstimateNdv::calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
ObCollationType coll_type = CS_TYPE_INVALID;
|
||||
type1.set_calc_type(ObVarcharType);
|
||||
type1.set_calc_collation_type(ObCharset::get_system_collation());
|
||||
OC((type_ctx.get_session()->get_collation_connection)(coll_type));
|
||||
type1.set_calc_collation_type(coll_type);
|
||||
type1.set_calc_collation_level(CS_LEVEL_IMPLICIT);
|
||||
if (OB_LIKELY(NOT_ROW_DIMENSION == row_dimension_)) {
|
||||
type.set_uint64();
|
||||
type.set_precision(ObAccuracy::DDL_DEFAULT_ACCURACY[ObUInt64Type].precision_);
|
||||
type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY[ObUInt64Type].scale_);
|
||||
if (lib::is_oracle_mode()) {
|
||||
type.set_number();
|
||||
type.set_scale(0);
|
||||
type.set_precision(OB_MAX_NUMBER_PRECISION);
|
||||
} else {
|
||||
type.set_type(ObIntType);
|
||||
type.set_scale(0);
|
||||
type.set_precision(MAX_BIGINT_WIDTH);
|
||||
}
|
||||
} else {
|
||||
ret = OB_ERR_INVALID_TYPE_FOR_OP;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprEstimateNdv::calc_result1(ObObj& result, const ObObj& obj, ObExprCtx& expr_ctx) const
|
||||
{
|
||||
return llc_estimate_ndv(result, obj, expr_ctx);
|
||||
}
|
||||
|
||||
int ObExprEstimateNdv::llc_estimate_ndv(ObObj& result, const ObObj& obj, ObExprCtx& expr_ctx)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_ctx);
|
||||
TYPE_CHECK(obj, ObVarcharType);
|
||||
const ObString& bitmap_str = obj.get_string();
|
||||
double res_double = 0.0;
|
||||
if (OB_FAIL(llc_estimate_ndv(res_double, bitmap_str))) {
|
||||
LOG_WARN("calculate estimate ndv failed.");
|
||||
} else if (OB_UNLIKELY(res_double >= DOUBLE_OVERFLOW_UINT64)) {
|
||||
LOG_WARN("estimate ndv value overflows", K(res_double));
|
||||
result.set_null();
|
||||
} else {
|
||||
result.set_uint64(static_cast<uint64_t>(res_double));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObExprEstimateNdv::llc_estimate_ndv(int64_t& result, const ObString& bitmap_str)
|
||||
void ObExprEstimateNdv::llc_estimate_ndv(int64_t &result, const ObString &bitmap_str)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
double res_double = 0.0;
|
||||
result = OB_INVALID_COUNT;
|
||||
if (OB_FAIL(llc_estimate_ndv(res_double, bitmap_str))) {
|
||||
LOG_WARN("calculate estimate ndv failed.");
|
||||
} else if (OB_UNLIKELY(res_double >= DOUBLE_OVERFLOW_UINT64)) {
|
||||
} else if (OB_UNLIKELY(res_double > UINT64_MAX)) {
|
||||
// 基本不会走到这里
|
||||
LOG_WARN("estimate ndv value overflows", K(res_double));
|
||||
} else {
|
||||
result = static_cast<int64_t>(res_double);
|
||||
@ -88,23 +79,24 @@ inline double ObExprEstimateNdv::llc_alpha_times_m_square(const uint64_t m)
|
||||
{
|
||||
double alpha = 0.0;
|
||||
switch (m) {
|
||||
case 16:
|
||||
alpha = 0.673;
|
||||
break;
|
||||
case 32:
|
||||
alpha = 0.697;
|
||||
break;
|
||||
case 64:
|
||||
alpha = 0.709;
|
||||
break;
|
||||
default:
|
||||
alpha = 0.7213 / (1 + 1.079 / static_cast<double>(m));
|
||||
break;
|
||||
case 16:
|
||||
alpha = 0.673;
|
||||
break;
|
||||
case 32:
|
||||
alpha = 0.697;
|
||||
break;
|
||||
case 64:
|
||||
alpha = 0.709;
|
||||
break;
|
||||
default:
|
||||
alpha = 0.7213 / (1 + 1.079 / static_cast<double>(m));
|
||||
break;
|
||||
}
|
||||
return alpha * static_cast<double>(m) * static_cast<double>(m);
|
||||
return alpha * static_cast<double>(m) * static_cast<double>(m);
|
||||
}
|
||||
|
||||
int ObExprEstimateNdv::llc_estimate_ndv(double& estimate_ndv, const ObString& bitmap_buf)
|
||||
int ObExprEstimateNdv::llc_estimate_ndv(double &estimate_ndv,
|
||||
const ObString &bitmap_buf)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
double sum_of_pmax = 0.0;
|
||||
@ -121,14 +113,14 @@ int ObExprEstimateNdv::llc_estimate_ndv(double& estimate_ndv, const ObString& bi
|
||||
}
|
||||
}
|
||||
estimate_ndv = llc_alpha_times_m_square(llc_num_buckets) / sum_of_pmax;
|
||||
if (OB_UNLIKELY(estimate_ndv >= DOUBLE_OVERFLOW_UINT64)) {
|
||||
if (OB_UNLIKELY(estimate_ndv > UINT64_MAX)) {
|
||||
LOG_WARN("estimate ndv value overflows", K(estimate_ndv));
|
||||
} else {
|
||||
if (estimate_ndv <= 2.5 * static_cast<double>(llc_num_buckets)) {
|
||||
if (0 != num_empty_buckets) {
|
||||
// use linear count
|
||||
estimate_ndv = static_cast<double>(llc_num_buckets) *
|
||||
log(static_cast<double>(llc_num_buckets) / static_cast<double>(num_empty_buckets));
|
||||
estimate_ndv = static_cast<double>(llc_num_buckets)
|
||||
* log(static_cast<double>(llc_num_buckets) / static_cast<double>(num_empty_buckets));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,35 +130,44 @@ int ObExprEstimateNdv::llc_estimate_ndv(double& estimate_ndv, const ObString& bi
|
||||
|
||||
bool ObExprEstimateNdv::llc_is_num_buckets_valid(int64_t num_buckets)
|
||||
{
|
||||
return (num_buckets >= LLC_NUM_BUCKETS_MIN) && (num_buckets <= LLC_NUM_BUCKETS_MAX) &&
|
||||
!(num_buckets & (num_buckets - 1));
|
||||
// 要求 LLC_NUM_BUCKETS_MIN <= 桶数 <= LLC_NUM_BUCKETS_MAX 且是2的次幂
|
||||
return (num_buckets >= LLC_NUM_BUCKETS_MIN)
|
||||
&& (num_buckets <= LLC_NUM_BUCKETS_MAX)
|
||||
&& !(num_buckets & (num_buckets - 1));
|
||||
}
|
||||
|
||||
int ObExprEstimateNdv::calc_estimate_ndv_expr(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& res_datum)
|
||||
int ObExprEstimateNdv::calc_estimate_ndv_expr(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum* arg = NULL;
|
||||
ObDatum *arg = NULL;
|
||||
double res_double = 0.0;
|
||||
if (OB_FAIL(expr.eval_param_value(ctx, arg))) {
|
||||
LOG_WARN("eval arg failed", K(ret));
|
||||
} else if (arg->is_null()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("arg cannot be null", K(ret));
|
||||
} else {
|
||||
const ObString& bitmap_str = arg->get_string();
|
||||
double res_double = 0.0;
|
||||
if (OB_FAIL(ObExprEstimateNdv::llc_estimate_ndv(res_double, bitmap_str))) {
|
||||
LOG_WARN("calculate estimate ndv failed.");
|
||||
} else if (OB_UNLIKELY(res_double >= DOUBLE_OVERFLOW_UINT64)) {
|
||||
LOG_WARN("estimate ndv value overflows", K(res_double));
|
||||
res_datum.set_null();
|
||||
} else if (!arg->is_null() &&
|
||||
OB_FAIL(ObExprEstimateNdv::llc_estimate_ndv(res_double, arg->get_string()))) {
|
||||
LOG_WARN("calculate estimate ndv failed.");
|
||||
} else if (OB_UNLIKELY(res_double > INT64_MAX)) {
|
||||
// 基本不会走到这里
|
||||
LOG_WARN("estimate ndv value overflows", K(res_double));
|
||||
res_datum.set_null();
|
||||
} else if (lib::is_oracle_mode()) {
|
||||
number::ObNumber result_num;
|
||||
char local_buff[number::ObNumber::MAX_BYTE_LEN];
|
||||
ObDataBuffer local_alloc(local_buff, number::ObNumber::MAX_BYTE_LEN);
|
||||
if (OB_FAIL(result_num.from(static_cast<int64_t>(res_double), local_alloc))) {
|
||||
LOG_WARN("fail to call from", K(ret));
|
||||
} else {
|
||||
res_datum.set_uint(static_cast<uint64_t>(res_double));
|
||||
res_datum.set_number(result_num);
|
||||
}
|
||||
} else {
|
||||
res_datum.set_int(static_cast<int64_t>(res_double));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprEstimateNdv::cg_expr(ObExprCGCtx& expr_cg_ctx, const ObRawExpr& raw_expr, ObExpr& rt_expr) const
|
||||
int ObExprEstimateNdv::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr_cg_ctx);
|
||||
|
||||
Reference in New Issue
Block a user