[FEAT MERGE]4_1_sql_feature
Co-authored-by: leslieyuchen <leslieyuchen@gmail.com> Co-authored-by: Charles0429 <xiezhenjiang@gmail.com> Co-authored-by: raywill <hustos@gmail.com>
This commit is contained in:
469
src/sql/ob_optimizer_trace_impl.h
Normal file
469
src/sql/ob_optimizer_trace_impl.h
Normal file
@ -0,0 +1,469 @@
|
||||
/**
|
||||
* ob_optimizer_trace_impl.h
|
||||
*
|
||||
* Authors:
|
||||
* zhenling.zzg <zhenling.zzg@alipay.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _OB_OPTIMIZER_TRACE_IMPL_H
|
||||
#define _OB_OPTIMIZER_TRACE_IMPL_H
|
||||
|
||||
#include "lib/file/ob_file.h"
|
||||
#include "lib/allocator/ob_allocator.h"
|
||||
#include "lib/hash_func/murmur_hash.h"
|
||||
#include "common/storage/ob_io_device.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr_printer.h"
|
||||
#include "common/ob_smart_call.h"
|
||||
#include "lib/container/ob_array.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace common {
|
||||
class ObObj;
|
||||
}
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
class ObDMLStmt;
|
||||
class ObSelectStmt;
|
||||
class ObRawExpr;
|
||||
class ObLogPlan;
|
||||
class ObJoinOrder;
|
||||
class Path;
|
||||
class JoinPath;
|
||||
struct JoinInfo;
|
||||
class OptTableMetas;
|
||||
class TableItem;
|
||||
class ObSQLSessionInfo;
|
||||
|
||||
class ObOptimizerTraceImpl;
|
||||
|
||||
inline ObOptimizerTraceImpl** get_local_tracer()
|
||||
{
|
||||
// use thread local for raw thread.
|
||||
RLOCAL_INLINE(ObOptimizerTraceImpl*, optimizer_tracer);
|
||||
return &optimizer_tracer;
|
||||
}
|
||||
|
||||
#define TITLE_LINE "------------------------------------------------------"
|
||||
|
||||
#define KV(x) " ", #x, " = ", x
|
||||
#define KV_(x) " ", #x, " = ", x##_
|
||||
|
||||
#define BEGIN_OPT_TRACE(session, sql_id) \
|
||||
ObOptimizerTraceImpl *copy_tracer = NULL; \
|
||||
do { \
|
||||
ObOptimizerTraceImpl** local_tracer = get_local_tracer(); \
|
||||
if (OB_ISNULL(local_tracer) || OB_ISNULL(session)) { \
|
||||
} else { \
|
||||
copy_tracer = *local_tracer; \
|
||||
if (session->get_optimizer_tracer().enable(sql_id)) { \
|
||||
session->get_optimizer_tracer().open(); \
|
||||
} \
|
||||
*local_tracer = &(session->get_optimizer_tracer()); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define END_OPT_TRACE(session) \
|
||||
do { \
|
||||
ObOptimizerTraceImpl** local_tracer = get_local_tracer(); \
|
||||
if (OB_ISNULL(local_tracer) || OB_ISNULL(session)) { \
|
||||
} else { \
|
||||
if (session->get_optimizer_tracer().enable()) { \
|
||||
session->get_optimizer_tracer().close(); \
|
||||
} \
|
||||
*local_tracer = copy_tracer; \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define CHECK_TRACE \
|
||||
ObOptimizerTraceImpl** local_tracer = get_local_tracer(); \
|
||||
ObOptimizerTraceImpl *tracer = NULL; \
|
||||
if (OB_ISNULL(local_tracer) || \
|
||||
OB_ISNULL(tracer=*local_tracer)) { \
|
||||
} else \
|
||||
|
||||
#define CHECK_TRACE_ENABLED \
|
||||
CHECK_TRACE if (tracer->enable()) \
|
||||
|
||||
#define RESUME_OPT_TRACE \
|
||||
do { \
|
||||
CHECK_TRACE { \
|
||||
tracer->resume_trace(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define STOP_OPT_TRACE \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->stop_trace(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_BEGIN_SECTION \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->increase_section(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_END_SECTION \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->decrease_section(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE(args...) \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->new_line(); \
|
||||
SMART_CALL(tracer->append(args)); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_TITLE(args...) \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->append_title(args); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_ENV \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->append_title("SYSTEM ENVIRONMENT"); \
|
||||
tracer->trace_env(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_SESSION_INFO \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->append_title("SESSION INFO"); \
|
||||
tracer->trace_session_info(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_PARAMETERS \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->append_title("OPTIMIZER PARAMETERS");\
|
||||
tracer->trace_parameters(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_STATIS(stmt, table_metas) \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->append_title("BASIC TABLE STATIS"); \
|
||||
tracer->trace_static(stmt, table_metas); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_TRANSFORM_SQL(stmt) \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->trace_trans_sql(stmt); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_TIME_USED \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->trace_time_used(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
#define OPT_TRACE_MEM_USED \
|
||||
do { \
|
||||
CHECK_TRACE_ENABLED { \
|
||||
tracer->trace_mem_used(); \
|
||||
} \
|
||||
} while (0); \
|
||||
|
||||
class LogFileAppender {
|
||||
public:
|
||||
LogFileAppender();
|
||||
int open();
|
||||
void close();
|
||||
int set_identifier(const common::ObString &identifier);
|
||||
int append(const char* buf, int64_t buf_len);
|
||||
private:
|
||||
int check_log_file_full(bool &is_full);
|
||||
int generate_log_file_name();
|
||||
int open_log_file();
|
||||
private:
|
||||
static const int64_t MAX_LOG_FILE_SIZE = 256*1024*1024;
|
||||
common::ObArenaAllocator allocator_;
|
||||
common::ObFileAppender log_handle_;
|
||||
common::ObString identifier_;
|
||||
ObSqlString log_file_name_;
|
||||
};
|
||||
|
||||
class ObOptimizerTraceImpl
|
||||
{
|
||||
public:
|
||||
ObOptimizerTraceImpl();
|
||||
~ObOptimizerTraceImpl();
|
||||
int enable_trace(const common::ObString &identifier,
|
||||
const common::ObString &sql_id,
|
||||
const int trace_level);
|
||||
|
||||
int set_parameters(const common::ObString &identifier,
|
||||
const common::ObString &sql_id,
|
||||
const int trace_level);
|
||||
void reset();
|
||||
int open();
|
||||
void close();
|
||||
inline bool enable() const { return enable_; }
|
||||
bool enable(const common::ObString &sql_id);
|
||||
inline void set_enable(bool value) { enable_ = value; }
|
||||
inline bool enable_trace_trans_sql() const { return trace_level_ > 1; }
|
||||
inline bool enable_trace_time_used() const { return trace_level_ > 0; }
|
||||
inline bool enable_trace_mem_used() const { return trace_level_ > 0; }
|
||||
inline void increase_section() { ++section_; }
|
||||
inline void decrease_section() { if (section_ > 0) --section_; }
|
||||
inline void set_session_info(ObSQLSessionInfo* info) { session_info_ = info; }
|
||||
void resume_trace();
|
||||
void stop_trace();
|
||||
|
||||
/***********************************************/
|
||||
////print basic type
|
||||
/***********************************************/
|
||||
int new_line();
|
||||
int append_lower(const char* msg);
|
||||
int append();
|
||||
int append(const bool &value);
|
||||
int append(const char* msg);
|
||||
int append(const common::ObString &msg);
|
||||
int append(const int64_t &value);
|
||||
int append(const uint64_t &value);
|
||||
int append(const uint32_t &value);
|
||||
int append(const double & value);
|
||||
int append(const ObObj& value);
|
||||
/***********************************************/
|
||||
////print plan info
|
||||
/***********************************************/
|
||||
int append(const ObLogPlan *log_plan);
|
||||
int append(const ObJoinOrder *join_order);
|
||||
int append(const Path *value);
|
||||
int append(const JoinPath *value);
|
||||
int append(const JoinInfo& info);
|
||||
int append(const TableItem *table);
|
||||
/***********************************************/
|
||||
////print template type
|
||||
/***********************************************/
|
||||
//for class ObRawExpr
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObRawExpr, T>::value, int>::type
|
||||
append(const T* expr);
|
||||
|
||||
//for class ObDMLStmt
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObDMLStmt, T>::value, int>::type
|
||||
append(const T* value);
|
||||
|
||||
//for ObIArray<ObRawExpr*>
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObIArray<ObRawExpr*>, T>::value, int>::type
|
||||
append(const T& value);
|
||||
|
||||
//for ObIArray<uint64_t>
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObIArray<uint64_t>, T>::value, int>::type
|
||||
append(const T& value);
|
||||
|
||||
//for ObIArray<int64_t>
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObIArray<int64_t>, T>::value, int>::type
|
||||
append(const T& value);
|
||||
|
||||
//template for function append
|
||||
template<typename T1, typename T2, typename ...ARGS>
|
||||
int append(const T1& value1, const T2& value2, const ARGS&... args);
|
||||
/***********************************************/
|
||||
|
||||
template<typename ...ARGS>
|
||||
int append_key_value(const char* key, const ARGS&... args);
|
||||
|
||||
template<typename ...ARGS>
|
||||
int append_title(const ARGS&... args);
|
||||
|
||||
int trace_env();
|
||||
int trace_parameters();
|
||||
int trace_session_info();
|
||||
int trace_static(const ObDMLStmt *stmt, OptTableMetas &table_metas);
|
||||
int trace_trans_sql(const ObDMLStmt *stmt);
|
||||
int trace_time_used();
|
||||
int trace_mem_used();
|
||||
private:
|
||||
common::ObArenaAllocator allocator_;
|
||||
LogFileAppender log_handle_;
|
||||
common::ObString sql_id_;
|
||||
ObSQLSessionInfo *session_info_;
|
||||
int64_t start_time_us_;
|
||||
int64_t last_time_us_;
|
||||
int64_t last_mem_;
|
||||
int section_;
|
||||
int trace_level_;
|
||||
bool enable_;
|
||||
bool trace_state_before_stop_;
|
||||
};
|
||||
|
||||
//for class ObRawExpr
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObRawExpr, T>::value, int>::type
|
||||
ObOptimizerTraceImpl::append(const T* expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = NULL;
|
||||
int64_t buf_len = OB_MAX_SQL_LENGTH;
|
||||
int64_t pos = 0;
|
||||
if (OB_ISNULL(buf = (char*)allocator_.alloc(buf_len))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
//LOG_WARN("failed to alloc buffer", K(ret));
|
||||
} else if (OB_NOT_NULL(expr)) {
|
||||
// TODO: @zhenling, use a valid schema guard in each query
|
||||
ObRawExprPrinter expr_printer(buf, buf_len, &pos, NULL);
|
||||
const ObRawExpr *raw_expr = static_cast<const ObRawExpr*>(expr);
|
||||
if (OB_FAIL(expr_printer.do_print(const_cast<ObRawExpr*>(raw_expr), T_NONE_SCOPE))) {
|
||||
//LOG_WARN("failed to print expr", K(ret));
|
||||
} else if (OB_FAIL(log_handle_.append(buf, pos))) {
|
||||
//LOG_WARN("failed to append expr", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//for class ObDMLStmt
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObDMLStmt, T>::value, int>::type
|
||||
ObOptimizerTraceImpl::append(const T* value)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObString sql;
|
||||
ObObjPrintParams print_params;
|
||||
// TODO: @zhenling, use a valid schema guard in each query
|
||||
if (OB_FAIL(ObSQLUtils::reconstruct_sql(allocator_,
|
||||
value,
|
||||
sql,
|
||||
NULL,
|
||||
print_params))) {
|
||||
//LOG_WARN("failed to construct sql", K(ret));
|
||||
} else if (OB_FAIL(append(sql))) {
|
||||
//LOG_WARN("failed to append sql", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//for ObIArray<ObRawExpr*>
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObIArray<ObRawExpr*>, T>::value, int>::type
|
||||
ObOptimizerTraceImpl::append(const T& value)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
append("[");
|
||||
for (int i = 0; OB_SUCC(ret) && i < value.count(); ++i) {
|
||||
if (i > 0) {
|
||||
append(", ");
|
||||
}
|
||||
ret = append(value.at(i));
|
||||
}
|
||||
append("]");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//for ObIArray<uint64_t>
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObIArray<uint64_t>, T>::value, int>::type
|
||||
ObOptimizerTraceImpl::append(const T& value)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
append("[");
|
||||
for (int i = 0; OB_SUCC(ret) && i < value.count(); ++i) {
|
||||
if (i > 0) {
|
||||
append(", ");
|
||||
}
|
||||
ret = append(value.at(i));
|
||||
}
|
||||
append("]");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//for ObIArray<int64_t>
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_base_of<ObIArray<int64_t>, T>::value, int>::type
|
||||
ObOptimizerTraceImpl::append(const T& value)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
append("[");
|
||||
for (int i = 0; OB_SUCC(ret) && i < value.count(); ++i) {
|
||||
if (i > 0) {
|
||||
append(", ");
|
||||
}
|
||||
ret = append(value.at(i));
|
||||
}
|
||||
append("]");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//template for function append
|
||||
template<typename T1, typename T2, typename ...ARGS>
|
||||
int ObOptimizerTraceImpl::append(const T1& value1, const T2& value2, const ARGS&... args)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(append(value1))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(" "))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(value2))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(" "))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(args...))) {
|
||||
//LOG_WARN
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename ...ARGS>
|
||||
int ObOptimizerTraceImpl::append_key_value(const char* key, const ARGS&... args)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(append(key))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(":\t"))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(args...))) {
|
||||
//LOG_WARN
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename ...ARGS>
|
||||
int ObOptimizerTraceImpl::append_title(const ARGS&... args)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(new_line())) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(TITLE_LINE))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(new_line())) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(args...))) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(new_line())) {
|
||||
//LOG_WARN
|
||||
} else if (OB_FAIL(append(TITLE_LINE))) {
|
||||
//LOG_WARN
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _OB_OPTIMIZER_TRACE_IMPL_H */
|
||||
Reference in New Issue
Block a user