[Optimize] optimize some session variable and profile (#6920)
1. optimize error message when using batch delete 2. rename session variable is_report_success to enable_profile 3. add table name to OlapScanner profile
This commit is contained in:
@ -96,7 +96,11 @@ Status OlapScanNode::init(const TPlanNode& tnode, RuntimeState* state) {
|
||||
}
|
||||
|
||||
void OlapScanNode::init_scan_profile() {
|
||||
_scanner_profile.reset(new RuntimeProfile("OlapScanner"));
|
||||
std::string scanner_profile_name = "OlapScanner";
|
||||
if (_olap_scan_node.__isset.table_name) {
|
||||
scanner_profile_name = fmt::format("OlapScanner({0})", _olap_scan_node.table_name);
|
||||
}
|
||||
_scanner_profile.reset(new RuntimeProfile(scanner_profile_name));
|
||||
runtime_profile()->add_child(_scanner_profile.get(), true, NULL);
|
||||
|
||||
_segment_profile.reset(new RuntimeProfile("SegmentIterator"));
|
||||
|
||||
@ -463,7 +463,7 @@ We will only discuss the case of a single BE. If the user cluster has more than
|
||||
|
||||
### Performance analysis
|
||||
|
||||
You can execute `set is_report_success=true` to open the load job profile before submitting the import job. After the import job is completed, you can view the profile of the import job in the `Queris` tab of the FE web page.
|
||||
You can execute `set enable_profile=true` to open the load job profile before submitting the import job. After the import job is completed, you can view the profile of the import job in the `Queris` tab of the FE web page.
|
||||
|
||||
This profile can help analyze the running status of the import job.
|
||||
|
||||
|
||||
@ -44,10 +44,10 @@ FE splits the query plan into fragments and distributes them to BE for task exec
|
||||
Turn on the report switch on FE through MySQL command
|
||||
|
||||
```
|
||||
mysql> set is_report_success=true;
|
||||
mysql> set enable_profile=true;
|
||||
```
|
||||
|
||||
After executing the corresponding SQL statement, we can see the report information of the corresponding SQL statement on the FE web page like the picture below.
|
||||
After executing the corresponding SQL statement(`is_report_success` in old versions), we can see the report information of the corresponding SQL statement on the FE web page like the picture below.
|
||||

|
||||
|
||||
The latest **100 statements** executed will be listed here. We can view detailed statistics of RunningProfile.
|
||||
|
||||
@ -251,7 +251,7 @@ EXPLAIN SELECT t1 FROM test JOIN test2 where test.t1 = test2.t2;
|
||||
SELECT t1 FROM test JOIN test2 where test.t1 = test2.t2;
|
||||
-- Return 2 rows of results [3, 4];
|
||||
|
||||
-- Through the query profile (set is_report_success=true;) you can view the detailed information of the internal work of the query,
|
||||
-- Through the query profile (set enable_profile=true;) you can view the detailed information of the internal work of the query,
|
||||
-- Including whether each Runtime Filter is pushed down, waiting time,
|
||||
-- and the total time from prepare to receiving Runtime Filter for OLAP_SCAN_NODE.
|
||||
RuntimeFilter:in:
|
||||
|
||||
@ -67,7 +67,7 @@ Variables that support both session-level and global-level setting include:
|
||||
* `time_zone`
|
||||
* `wait_timeout`
|
||||
* `sql_mode`
|
||||
* `is_report_success`
|
||||
* `enable_profile`
|
||||
* `query_timeout`
|
||||
* `exec_mem_limit`
|
||||
* `batch_size`
|
||||
@ -229,7 +229,7 @@ Note that the comment must start with /*+ and can only follow the SELECT.
|
||||
|
||||
Used for compatibility with MySQL clients. No practical effect.
|
||||
|
||||
* `is_report_success`
|
||||
* `enable_profile`
|
||||
|
||||
Used to set whether you need to view the profile of the query. The default is false, which means no profile is required.
|
||||
|
||||
@ -239,7 +239,7 @@ Note that the comment must start with /*+ and can only follow the SELECT.
|
||||
|
||||
`fe_host:fe_http:port/query`
|
||||
|
||||
It will display the most recent 100 queries which `is_report_success` is set to true.
|
||||
It will display the most recent 100 queries which `enable_profile` is set to true.
|
||||
|
||||
* `language`
|
||||
|
||||
|
||||
@ -472,7 +472,7 @@ LoadFinishTime: 2019-07-27 11:50:16
|
||||
|
||||
### 性能分析
|
||||
|
||||
可以在提交 LOAD 作业前,先执行 `set is_report_success=true` 打开会话变量。然后提交导入作业。待导入作业完成后,可以在 FE 的 web 页面的 `Queris` 标签中查看到导入作业的 Profile。
|
||||
可以在提交 LOAD 作业前,先执行 `set enable_profile=true` 打开会话变量。然后提交导入作业。待导入作业完成后,可以在 FE 的 web 页面的 `Queris` 标签中查看到导入作业的 Profile。
|
||||
|
||||
这个 Profile 可以帮助分析导入作业的运行状态。
|
||||
|
||||
|
||||
@ -44,10 +44,10 @@ FE将查询计划拆分成为Fragment下发到BE进行任务执行。BE在执行
|
||||
通过Mysql命令,将FE上的Report的开关打开
|
||||
|
||||
```
|
||||
mysql> set is_report_success=true;
|
||||
mysql> set enable_profile=true;
|
||||
```
|
||||
|
||||
之后执行对应的SQL语句之后,在FE的Web页面就可以看到对应SQL语句执行的Report信息:
|
||||
之后执行对应的SQL语句之后(旧版本为`is_report_success`),在FE的Web页面就可以看到对应SQL语句执行的Report信息:
|
||||

|
||||
|
||||
这里会列出最新执行完成的**100条语句**,我们可以通过Profile查看详细的统计信息。
|
||||
|
||||
@ -251,7 +251,7 @@ EXPLAIN SELECT t1 FROM test JOIN test2 where test.t1 = test2.t2;
|
||||
SELECT t1 FROM test JOIN test2 where test.t1 = test2.t2;
|
||||
-- 返回2行结果[3, 4];
|
||||
|
||||
-- 通过query的profile(set is_report_success=true;)可以查看查询内部工作的详细信息,
|
||||
-- 通过query的profile(set enable_profile=true;)可以查看查询内部工作的详细信息,
|
||||
-- 包括每个Runtime Filter是否下推、等待耗时、以及OLAP_SCAN_NODE从prepare到接收到Runtime Filter的总时长。
|
||||
RuntimeFilter:in:
|
||||
- HasPushDownToEngine: true
|
||||
|
||||
@ -67,7 +67,7 @@ SET GLOBAL exec_mem_limit = 137438953472
|
||||
* `time_zone`
|
||||
* `wait_timeout`
|
||||
* `sql_mode`
|
||||
* `is_report_success`
|
||||
* `enable_profile`
|
||||
* `query_timeout`
|
||||
* `exec_mem_limit`
|
||||
* `batch_size`
|
||||
@ -226,7 +226,7 @@ SELECT /*+ SET_VAR(query_timeout = 1, enable_partition_cache=true) */ sleep(3);
|
||||
|
||||
用于兼容 MySQL 客户端。无实际作用。
|
||||
|
||||
* `is_report_success`
|
||||
* `enable_profile`
|
||||
|
||||
用于设置是否需要查看查询的 profile。默认为 false,即不需要 profile。
|
||||
|
||||
@ -235,7 +235,7 @@ SELECT /*+ SET_VAR(query_timeout = 1, enable_partition_cache=true) */ sleep(3);
|
||||
|
||||
`fe_host:fe_http_port/query`
|
||||
|
||||
其中会显示最近100条,开启 `is_report_success` 的查询的 profile。
|
||||
其中会显示最近100条,开启 `enable_profile` 的查询的 profile。
|
||||
|
||||
* `language`
|
||||
|
||||
|
||||
@ -810,7 +810,13 @@ public class SchemaChangeHandler extends AlterHandler {
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
throw new DdlException("Can not add column which already exists in base table: " + newColName);
|
||||
if (newColName.equalsIgnoreCase(Column.DELETE_SIGN)) {
|
||||
throw new DdlException("Can not enable batch delete support, already supported batch delete.");
|
||||
} else if (newColName.equalsIgnoreCase(Column.SEQUENCE_COL)) {
|
||||
throw new DdlException("Can not enable sequence column support, already supported sequence column.");
|
||||
} else {
|
||||
throw new DdlException("Can not add column which already exists in base table: " + newColName);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -129,23 +129,26 @@ public class SetVar {
|
||||
}
|
||||
}
|
||||
|
||||
if (getVariable().toLowerCase().equals("prefer_join_method")) {
|
||||
if (getVariable().equalsIgnoreCase(SessionVariable.PREFER_JOIN_METHOD)) {
|
||||
String value = getValue().getStringValue();
|
||||
if (!value.toLowerCase().equals("broadcast") && !value.toLowerCase().equals("shuffle")) {
|
||||
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_VALUE_FOR_VAR, "prefer_join_method", value);
|
||||
if (!value.equalsIgnoreCase("broadcast") && !value.equalsIgnoreCase("shuffle")) {
|
||||
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_VALUE_FOR_VAR, SessionVariable.PREFER_JOIN_METHOD, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Check variable time_zone value is valid
|
||||
if (getVariable().toLowerCase().equals("time_zone")) {
|
||||
if (getVariable().equalsIgnoreCase(SessionVariable.TIME_ZONE)) {
|
||||
this.value = new StringLiteral(TimeUtils.checkTimeZoneValidAndStandardize(getValue().getStringValue()));
|
||||
this.result = (LiteralExpr) this.value;
|
||||
}
|
||||
|
||||
if (getVariable().toLowerCase().equals("exec_mem_limit")) {
|
||||
if (getVariable().equalsIgnoreCase(SessionVariable.EXEC_MEM_LIMIT)) {
|
||||
this.value = new StringLiteral(Long.toString(ParseUtil.analyzeDataVolumn(getValue().getStringValue())));
|
||||
this.result = (LiteralExpr) this.value;
|
||||
}
|
||||
if (getVariable().equalsIgnoreCase("is_report_success")) {
|
||||
variable = SessionVariable.ENABLE_PROFILE;
|
||||
}
|
||||
}
|
||||
|
||||
public String toSql() {
|
||||
|
||||
@ -1065,8 +1065,14 @@ public class Load {
|
||||
for (SlotRef slot : slots) {
|
||||
SlotDescriptor slotDesc = slotDescByName.get(slot.getColumnName());
|
||||
if (slotDesc == null) {
|
||||
throw new UserException("unknown reference column, column=" + entry.getKey()
|
||||
+ ", reference=" + slot.getColumnName());
|
||||
if (entry.getKey().equalsIgnoreCase(Column.DELETE_SIGN)) {
|
||||
throw new UserException("unknown reference column in DELETE ON clause:" + slot.getColumnName());
|
||||
} else if (entry.getKey().equalsIgnoreCase(Column.SEQUENCE_COL)) {
|
||||
throw new UserException("unknown reference column in ORDER BY clause:" + slot.getColumnName());
|
||||
} else {
|
||||
throw new UserException("unknown reference column, column=" + entry.getKey()
|
||||
+ ", reference=" + slot.getColumnName());
|
||||
}
|
||||
}
|
||||
smap.getLhs().add(slot);
|
||||
smap.getRhs().add(new SlotRef(slotDesc));
|
||||
@ -1099,8 +1105,14 @@ public class Load {
|
||||
smap.getRhs().add(new CastExpr(tbl.getColumn(slot.getColumnName()).getType(),
|
||||
exprsByName.get(slot.getColumnName())));
|
||||
} else {
|
||||
throw new UserException("unknown reference column, column=" + entry.getKey()
|
||||
+ ", reference=" + slot.getColumnName());
|
||||
if (entry.getKey().equalsIgnoreCase(Column.DELETE_SIGN)) {
|
||||
throw new UserException("unknown reference column in DELETE ON clause:" + slot.getColumnName());
|
||||
} else if (entry.getKey().equalsIgnoreCase(Column.SEQUENCE_COL)) {
|
||||
throw new UserException("unknown reference column in ORDER BY clause:" + slot.getColumnName());
|
||||
} else {
|
||||
throw new UserException("unknown reference column, column=" + entry.getKey()
|
||||
+ ", reference=" + slot.getColumnName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr expr = entry.getValue().clone(smap);
|
||||
|
||||
@ -75,7 +75,7 @@ public class BrokerLoadJob extends BulkLoadJob {
|
||||
// Profile of this load job, including all tasks' profiles
|
||||
private RuntimeProfile jobProfile;
|
||||
// If set to true, the profile of load job with be pushed to ProfileManager
|
||||
private boolean isReportSuccess = false;
|
||||
private boolean enableProfile = false;
|
||||
|
||||
// for log replay and unit test
|
||||
public BrokerLoadJob() {
|
||||
@ -87,8 +87,8 @@ public class BrokerLoadJob extends BulkLoadJob {
|
||||
throws MetaNotFoundException {
|
||||
super(EtlJobType.BROKER, dbId, label, originStmt, userInfo);
|
||||
this.brokerDesc = brokerDesc;
|
||||
if (ConnectContext.get() != null && ConnectContext.get().getSessionVariable().isReportSucc()) {
|
||||
isReportSuccess = true;
|
||||
if (ConnectContext.get() != null && ConnectContext.get().getSessionVariable().enableProfile()) {
|
||||
enableProfile = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ public class BrokerLoadJob extends BulkLoadJob {
|
||||
LoadLoadingTask task = new LoadLoadingTask(db, table, brokerDesc,
|
||||
brokerFileGroups, getDeadlineMs(), getExecMemLimit(),
|
||||
isStrictMode(), transactionId, this, getTimeZone(), getTimeout(),
|
||||
getLoadParallelism(), getSendBatchParallelism(), isReportSuccess ? jobProfile : null);
|
||||
getLoadParallelism(), getSendBatchParallelism(), enableProfile ? jobProfile : null);
|
||||
UUID uuid = UUID.randomUUID();
|
||||
TUniqueId loadId = new TUniqueId(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
|
||||
task.init(loadId, attachment.getFileStatusByTable(aggKey),
|
||||
@ -306,7 +306,7 @@ public class BrokerLoadJob extends BulkLoadJob {
|
||||
}
|
||||
|
||||
private void writeProfile() {
|
||||
if (!isReportSuccess) {
|
||||
if (!enableProfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -759,6 +759,7 @@ public class OlapScanNode extends ScanNode {
|
||||
msg.olap_scan_node.setSortColumn(sortColumn);
|
||||
}
|
||||
msg.olap_scan_node.setKeyType(olapTable.getKeysType().toThrift());
|
||||
msg.olap_scan_node.setTableName(olapTable.getName());
|
||||
}
|
||||
|
||||
// export some tablets
|
||||
|
||||
@ -239,7 +239,7 @@ public class Coordinator {
|
||||
}
|
||||
this.tResourceInfo = new TResourceInfo(context.getQualifiedUser(),
|
||||
context.getSessionVariable().getResourceGroup());
|
||||
this.needReport = context.getSessionVariable().isReportSucc();
|
||||
this.needReport = context.getSessionVariable().enableProfile();
|
||||
this.nextInstanceId = new TUniqueId();
|
||||
nextInstanceId.setHi(queryId.hi);
|
||||
nextInstanceId.setLo(queryId.lo + 1);
|
||||
|
||||
@ -82,7 +82,6 @@ public final class GlobalVariable {
|
||||
|
||||
// Don't allow create instance.
|
||||
private GlobalVariable() {
|
||||
|
||||
}
|
||||
|
||||
public static List<String> getPersistentGlobalVarNames() {
|
||||
|
||||
@ -162,7 +162,7 @@ public final class QeProcessorImpl implements QeProcessor {
|
||||
.db(context.getDatabase())
|
||||
.fragmentInstanceInfos(info.getCoord().getFragmentInstanceInfos())
|
||||
.profile(info.getCoord().getQueryProfile())
|
||||
.isReportSucc(context.getSessionVariable().isReportSucc()).build();
|
||||
.isReportSucc(context.getSessionVariable().enableProfile()).build();
|
||||
querySet.put(queryIdStr, item);
|
||||
}
|
||||
return querySet;
|
||||
|
||||
@ -45,7 +45,7 @@ public class SessionVariable implements Serializable, Writable {
|
||||
|
||||
public static final String EXEC_MEM_LIMIT = "exec_mem_limit";
|
||||
public static final String QUERY_TIMEOUT = "query_timeout";
|
||||
public static final String IS_REPORT_SUCCESS = "is_report_success";
|
||||
public static final String ENABLE_PROFILE = "enable_profile";
|
||||
public static final String SQL_MODE = "sql_mode";
|
||||
public static final String RESOURCE_VARIABLE = "resource_group";
|
||||
public static final String AUTO_COMMIT = "autocommit";
|
||||
@ -186,8 +186,8 @@ public class SessionVariable implements Serializable, Writable {
|
||||
public int queryTimeoutS = 300;
|
||||
|
||||
// if true, need report to coordinator when plan fragment execute successfully.
|
||||
@VariableMgr.VarAttr(name = IS_REPORT_SUCCESS, needForward = true)
|
||||
public boolean isReportSucc = false;
|
||||
@VariableMgr.VarAttr(name = ENABLE_PROFILE, needForward = true)
|
||||
public boolean enableProfile = false;
|
||||
|
||||
// Set sqlMode to empty string
|
||||
@VariableMgr.VarAttr(name = SQL_MODE, needForward = true)
|
||||
@ -396,8 +396,8 @@ public class SessionVariable implements Serializable, Writable {
|
||||
return queryTimeoutS;
|
||||
}
|
||||
|
||||
public boolean isReportSucc() {
|
||||
return isReportSucc;
|
||||
public boolean enableProfile() {
|
||||
return enableProfile;
|
||||
}
|
||||
|
||||
public int getWaitTimeoutS() {
|
||||
@ -813,7 +813,7 @@ public class SessionVariable implements Serializable, Writable {
|
||||
tResult.setBufferPoolLimit(maxExecMemByte);
|
||||
|
||||
tResult.setQueryTimeout(queryTimeoutS);
|
||||
tResult.setIsReportSuccess(isReportSucc);
|
||||
tResult.setIsReportSuccess(enableProfile);
|
||||
tResult.setCodegenLevel(codegenLevel);
|
||||
tResult.setEnableVectorizedEngine(enableVectorizedEngine);
|
||||
|
||||
@ -913,7 +913,7 @@ public class SessionVariable implements Serializable, Writable {
|
||||
Text.readString(in);
|
||||
sqlMode = 0L;
|
||||
}
|
||||
isReportSucc = in.readBoolean();
|
||||
enableProfile = in.readBoolean();
|
||||
queryTimeoutS = in.readInt();
|
||||
maxExecMemByte = in.readLong();
|
||||
if (Catalog.getCurrentCatalogJournalVersion() >= FeMetaVersion.VERSION_37) {
|
||||
|
||||
@ -465,7 +465,7 @@ public class StmtExecutor implements ProfileWriter {
|
||||
|
||||
@Override
|
||||
public void writeProfile(boolean isLastWriteProfile) {
|
||||
if (!context.getSessionVariable().isReportSucc()) {
|
||||
if (!context.getSessionVariable().enableProfile()) {
|
||||
return;
|
||||
}
|
||||
synchronized (writeProfileLock) {
|
||||
|
||||
@ -51,9 +51,9 @@ public class SessionVariablesTest {
|
||||
Assert.assertTrue(numOfForwardVars >= 6);
|
||||
Assert.assertEquals(numOfForwardVars, vars.size());
|
||||
|
||||
vars.put(SessionVariable.IS_REPORT_SUCCESS, "true");
|
||||
vars.put(SessionVariable.ENABLE_PROFILE, "true");
|
||||
sessionVariable.setForwardedSessionVariables(vars);
|
||||
Assert.assertEquals(true, sessionVariable.isReportSucc);
|
||||
Assert.assertEquals(true, sessionVariable.enableProfile);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -85,7 +85,7 @@ public class VariableMgrTest {
|
||||
SessionVariable var = VariableMgr.newSessionVariable();
|
||||
Assert.assertEquals(2147483648L, var.getMaxExecMemByte());
|
||||
Assert.assertEquals(300, var.getQueryTimeoutS());
|
||||
Assert.assertEquals(false, var.isReportSucc());
|
||||
Assert.assertEquals(false, var.enableProfile());
|
||||
Assert.assertEquals(0L, var.getSqlMode());
|
||||
|
||||
List<List<String>> rows = VariableMgr.dump(SetType.SESSION, var, null);
|
||||
|
||||
@ -343,6 +343,7 @@ struct TOlapScanNode {
|
||||
4: required bool is_preaggregation
|
||||
5: optional string sort_column
|
||||
6: optional Types.TKeysType keyType
|
||||
7: optional string table_name
|
||||
}
|
||||
|
||||
struct TEqJoinCondition {
|
||||
|
||||
Reference in New Issue
Block a user