This is an automated email from the ASF dual-hosted git repository. kxiao pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/doris.git
commit ee1a4ac4801040ac3b76900b36aff6c39a8d420f Author: Xiangyu Wang <dut.xian...@gmail.com> AuthorDate: Fri Aug 18 09:36:07 2023 +0800 [Fix](Nereids) fix sql-cache for nereids. (#22808) 1. should not use ((LogicalPlanAdapter)parsedStmt).getStatementContext().getOriginStatement().originStmt.toLowerCase() as the cache key (do not invoke toLowerCase()), for example: select * from tbl1 where k1 = 'a' is different with select * from tbl1 where k1 = 'A', so the cache should be missed. 2. according to issue 6735 , the cache key should contains all views' s ddl sql (including nested views) --- .../org/apache/doris/nereids/NereidsPlanner.java | 1 + .../org/apache/doris/nereids/StatementContext.java | 12 +++ .../doris/nereids/glue/LogicalPlanAdapter.java | 10 ++ .../doris/nereids/rules/analysis/BindRelation.java | 2 +- .../org/apache/doris/qe/cache/CacheAnalyzer.java | 26 +++-- .../java/org/apache/doris/qe/cache/SqlCache.java | 15 +-- .../org/apache/doris/qe/PartitionCacheTest.java | 112 ++++++++++++++++++++- 7 files changed, 160 insertions(+), 18 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java index 02df5e9fa4..25e5ff6baa 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java @@ -140,6 +140,7 @@ public class NereidsPlanner extends Planner { ArrayList<String> columnLabelList = physicalPlan.getOutput().stream().map(NamedExpression::getName) .collect(Collectors.toCollection(ArrayList::new)); logicalPlanAdapter.setColLabels(columnLabelList); + logicalPlanAdapter.setViews(statementContext.getViews()); } @VisibleForTesting diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/StatementContext.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/StatementContext.java index b96aea672e..21246a5c70 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/StatementContext.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/StatementContext.java @@ -18,6 +18,7 @@ package org.apache.doris.nereids; import org.apache.doris.analysis.StatementBase; +import org.apache.doris.catalog.View; import org.apache.doris.common.IdGenerator; import org.apache.doris.common.Pair; import org.apache.doris.nereids.memo.Group; @@ -36,7 +37,9 @@ import org.apache.doris.qe.OriginStatement; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import java.util.HashMap; import java.util.List; @@ -77,6 +80,7 @@ public class StatementContext { // Used to update consumer's stats private final Map<CTEId, List<Pair<Map<Slot, Slot>, Group>>> cteIdToConsumerGroup = new HashMap<>(); private final Map<CTEId, LogicalPlan> rewrittenCtePlan = new HashMap<>(); + private final Set<View> views = Sets.newHashSet(); public StatementContext() { this.connectContext = ConnectContext.get(); @@ -206,4 +210,12 @@ public class StatementContext { public Map<CTEId, LogicalPlan> getRewrittenCtePlan() { return rewrittenCtePlan; } + + public void addView(View view) { + this.views.add(view); + } + + public List<View> getViews() { + return ImmutableList.copyOf(views); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/LogicalPlanAdapter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/LogicalPlanAdapter.java index 355cdfdec5..3c9c8d1a1b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/LogicalPlanAdapter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/LogicalPlanAdapter.java @@ -23,6 +23,7 @@ import org.apache.doris.analysis.OutFileClause; import org.apache.doris.analysis.Queriable; import org.apache.doris.analysis.RedirectStatus; import org.apache.doris.analysis.StatementBase; +import org.apache.doris.catalog.View; import org.apache.doris.nereids.StatementContext; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.commands.ExplainCommand; @@ -43,6 +44,7 @@ public class LogicalPlanAdapter extends StatementBase implements Queriable { private final LogicalPlan logicalPlan; private List<Expr> resultExprs; private ArrayList<String> colLabels; + private List<View> views; public LogicalPlanAdapter(LogicalPlan logicalPlan, StatementContext statementContext) { this.logicalPlan = logicalPlan; @@ -79,6 +81,10 @@ public class LogicalPlanAdapter extends StatementBase implements Queriable { return colLabels; } + public List<View> getViews() { + return views; + } + @Override public List<Expr> getResultExprs() { return resultExprs; @@ -92,6 +98,10 @@ public class LogicalPlanAdapter extends StatementBase implements Queriable { this.colLabels = colLabels; } + public void setViews(List<View> views) { + this.views = views; + } + public StatementContext getStatementContext() { return statementContext; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java index aff19c5441..3448e9a36a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java @@ -204,6 +204,7 @@ public class BindRelation extends OneAnalysisRuleFactory { case OLAP: return makeOlapScan(table, unboundRelation, tableQualifier); case VIEW: + cascadesContext.getStatementContext().addView((View) table); Plan viewPlan = parseAndAnalyzeView(((View) table).getDdlSql(), cascadesContext); return new LogicalSubQueryAlias<>(tableQualifier, viewPlan); case HMS_EXTERNAL_TABLE: @@ -254,7 +255,6 @@ public class BindRelation extends OneAnalysisRuleFactory { CascadesContext viewContext = CascadesContext.initContext( parentContext.getStatementContext(), parsedViewPlan, PhysicalProperties.ANY); viewContext.newAnalyzer().analyze(); - // we should remove all group expression of the plan which in other memo, so the groupId would not conflict return viewContext.getRewritePlan(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/cache/CacheAnalyzer.java b/fe/fe-core/src/main/java/org/apache/doris/qe/cache/CacheAnalyzer.java index 8fcf8811a8..980eb2d829 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/cache/CacheAnalyzer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/cache/CacheAnalyzer.java @@ -59,6 +59,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; /** * Analyze which caching mode a SQL is suitable for @@ -189,6 +190,10 @@ public class CacheAnalyzer { cacheMode = innerCheckCacheMode(now); } + public void checkCacheModeForNereids(long now) { + cacheMode = innerCheckCacheModeForNereids(now); + } + private CacheMode innerCheckCacheMode(long now) { if (!enableCache()) { LOG.debug("cache is disabled. queryid {}", DebugUtil.printId(queryId)); @@ -232,7 +237,7 @@ public class CacheAnalyzer { if (enableSqlCache() && (now - latestTable.latestTime) >= Config.cache_last_version_interval_second * 1000L) { if (LOG.isDebugEnabled()) { - LOG.debug("TIME:{},{},{}", now, latestTable.latestTime, + LOG.debug("Query cache time:{},{},{}", now, latestTable.latestTime, Config.cache_last_version_interval_second * 1000); } cache = new SqlCache(this.queryId, this.selectStmt); @@ -326,7 +331,7 @@ public class CacheAnalyzer { latestTable.debug(); addAllViewStmt((SetOperationStmt) parsedStmt); - String allViewExpandStmtListStr = parsedStmt.toSql() + "|" + StringUtils.join(allViewStmtSet, "|"); + String allViewExpandStmtListStr = StringUtils.join(allViewStmtSet, "|"); if (now == 0) { now = nowtime(); @@ -334,10 +339,10 @@ public class CacheAnalyzer { if (enableSqlCache() && (now - latestTable.latestTime) >= Config.cache_last_version_interval_second * 1000L) { if (LOG.isDebugEnabled()) { - LOG.debug("TIME:{},{},{}", now, latestTable.latestTime, + LOG.debug("Query cache time:{},{},{}", now, latestTable.latestTime, Config.cache_last_version_interval_second * 1000); } - cache = new SqlCache(this.queryId); + cache = new SqlCache(this.queryId, parsedStmt.toSql()); ((SqlCache) cache).setCacheInfo(this.latestTable, allViewExpandStmtListStr); MetricRepo.COUNTER_CACHE_ADDED_SQL.increase(1L); return CacheMode.Sql; @@ -383,19 +388,22 @@ public class CacheAnalyzer { return CacheMode.NoNeed; } - String cacheKey = ((LogicalPlanAdapter) parsedStmt).getStatementContext() - .getOriginStatement().originStmt.toLowerCase(); + allViewStmtSet.addAll(((LogicalPlanAdapter) parsedStmt).getViews() + .stream().map(view -> view.getDdlSql()).collect(Collectors.toSet())); + String allViewExpandStmtListStr = StringUtils.join(allViewStmtSet, "|"); + if (now == 0) { now = nowtime(); } if (enableSqlCache() && (now - latestTable.latestTime) >= Config.cache_last_version_interval_second * 1000L) { if (LOG.isDebugEnabled()) { - LOG.debug("TIME:{},{},{}", now, latestTable.latestTime, + LOG.debug("Query cache time :{},{},{}", now, latestTable.latestTime, Config.cache_last_version_interval_second * 1000); } - cache = new SqlCache(this.queryId); - ((SqlCache) cache).setCacheInfo(this.latestTable, cacheKey); + cache = new SqlCache(this.queryId, ((LogicalPlanAdapter) parsedStmt).getStatementContext() + .getOriginStatement().originStmt); + ((SqlCache) cache).setCacheInfo(this.latestTable, allViewExpandStmtListStr); MetricRepo.COUNTER_CACHE_ADDED_SQL.increase(1L); return CacheMode.Sql; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/cache/SqlCache.java b/fe/fe-core/src/main/java/org/apache/doris/qe/cache/SqlCache.java index 25b7233770..04f0ed35cb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/cache/SqlCache.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/cache/SqlCache.java @@ -31,12 +31,16 @@ import org.apache.logging.log4j.Logger; public class SqlCache extends Cache { private static final Logger LOG = LogManager.getLogger(SqlCache.class); + private String originSql; + public SqlCache(TUniqueId queryId, SelectStmt selectStmt) { super(queryId, selectStmt); } - public SqlCache(TUniqueId queryId) { + // For SetOperationStmt and Nereids + public SqlCache(TUniqueId queryId, String originSql) { super(queryId); + this.originSql = originSql; } public void setCacheInfo(CacheAnalyzer.CacheTable latestTable, String allViewExpandStmtListStr) { @@ -45,11 +49,10 @@ public class SqlCache extends Cache { } public String getSqlWithViewStmt() { - if (selectStmt != null) { - return selectStmt.toSql() + "|" + allViewExpandStmtListStr; - } else { - return allViewExpandStmtListStr; - } + String originSql = selectStmt != null ? selectStmt.toSql() : this.originSql; + String cacheKey = originSql + "|" + allViewExpandStmtListStr; + LOG.debug("Cache key: {}", cacheKey); + return cacheKey; } public InternalService.PFetchCacheResult getCacheData(Status status) { diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/PartitionCacheTest.java b/fe/fe-core/src/test/java/org/apache/doris/qe/PartitionCacheTest.java index 87345bcfa6..5923b57ea2 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/qe/PartitionCacheTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/qe/PartitionCacheTest.java @@ -45,6 +45,7 @@ import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; import org.apache.doris.common.UserException; import org.apache.doris.common.jmockit.Deencapsulation; +import org.apache.doris.common.telemetry.Telemetry; import org.apache.doris.common.util.SqlParserUtils; import org.apache.doris.common.util.Util; import org.apache.doris.datasource.CatalogMgr; @@ -54,6 +55,11 @@ import org.apache.doris.mysql.MysqlChannel; import org.apache.doris.mysql.MysqlSerializer; import org.apache.doris.mysql.privilege.AccessControllerManager; import org.apache.doris.mysql.privilege.MockedAuth; +import org.apache.doris.nereids.NereidsPlanner; +import org.apache.doris.nereids.StatementContext; +import org.apache.doris.nereids.glue.LogicalPlanAdapter; +import org.apache.doris.nereids.parser.NereidsParser; +import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.planner.OlapScanNode; import org.apache.doris.planner.PlanNodeId; import org.apache.doris.planner.ScanNode; @@ -235,6 +241,9 @@ public class PartitionCacheTest { QueryState state = new QueryState(); channel.reset(); + SessionVariable sessionVariable = new SessionVariable(); + Deencapsulation.setField(sessionVariable, "beNumber", 1); + new Expectations(channel) { { channel.getSerializer(); @@ -296,7 +305,6 @@ public class PartitionCacheTest { minTimes = 0; result = dbName; - SessionVariable sessionVariable = new SessionVariable(); ctx.getSessionVariable(); minTimes = 0; result = sessionVariable; @@ -307,6 +315,18 @@ public class PartitionCacheTest { ctx.getStmtId(); minTimes = 0; result = 1L; + + ctx.getTracer(); + minTimes = 0; + result = Telemetry.getNoopTracer(); + + ctx.getCurrentCatalog(); + minTimes = 0; + result = catalog; + + ctx.getCatalog(anyString); + minTimes = 0; + result = catalog; } }; @@ -466,10 +486,14 @@ public class PartitionCacheTest { List<Column> column = Lists.newArrayList(); column.add(column1); + column.add(column2); + column.add(column3); + column.add(column4); + column.add(column5); table.setIndexMeta(new Long(2), "test", column, 1, 1, shortKeyColumnCount, TStorageType.COLUMN, KeysType.AGG_KEYS); - Deencapsulation.setField(table, "baseIndexId", 1000); + Deencapsulation.setField(table, "baseIndexId", 2); table.addPartition(part12); table.addPartition(part13); @@ -519,6 +543,24 @@ public class PartitionCacheTest { return node; } + private StatementBase parseSqlByNereids(String sql) { + StatementBase stmt = null; + try { + LogicalPlan plan = new NereidsParser().parseSingle(sql); + OriginStatement originStatement = new OriginStatement(sql, 0); + StatementContext statementContext = new StatementContext(ctx, originStatement); + NereidsPlanner nereidsPlanner = new NereidsPlanner(statementContext); + LogicalPlanAdapter adapter = new LogicalPlanAdapter(plan, statementContext); + nereidsPlanner.plan(adapter); + statementContext.setParsedStatement(adapter); + stmt = adapter; + } catch (Throwable throwable) { + LOG.warn("Part,an_ex={}", throwable); + Assert.fail(throwable.getMessage()); + } + return stmt; + } + private StatementBase parseSql(String sql) { SqlParser parser = new SqlParser(new SqlScanner(new StringReader(sql))); StatementBase parseStmt = null; @@ -1099,6 +1141,24 @@ public class PartitionCacheTest { + "FROM appevent WHERE eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate"); } + @Test + public void testSqlCacheKeyWithViewForNereids() { + Env.getCurrentSystemInfo(); + StatementBase parseStmt = parseSqlByNereids("SELECT * from testDb.view1"); + ArrayList<Long> selectedPartitionIds + = Lists.newArrayList(20200112L, 20200113L, 20200114L); + List<ScanNode> scanNodes = Lists.newArrayList(createEventScanNode(selectedPartitionIds)); + CacheAnalyzer ca = new CacheAnalyzer(context, parseStmt, scanNodes); + ca.checkCacheModeForNereids(1579053661000L); //2020-1-15 10:01:01 + Assert.assertEquals(ca.getCacheMode(), CacheMode.Sql); + + SqlCache sqlCache = (SqlCache) ca.getCache(); + String cacheKey = sqlCache.getSqlWithViewStmt(); + Assert.assertEquals(cacheKey, "SELECT * from testDb.view1" + + "|select eventdate, COUNT(userid) FROM appevent " + + "WHERE eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate"); + } + @Test public void testSqlCacheKeyWithSubSelectView() { Env.getCurrentSystemInfo(); @@ -1125,6 +1185,35 @@ public class PartitionCacheTest { + "<= '2020-01-14') origin|select eventdate, userid FROM appevent"); } + + @Test + public void testSqlCacheKeyWithSubSelectViewForNereids() { + Env.getCurrentSystemInfo(); + StatementBase parseStmt = parseSqlByNereids( + "select origin.eventdate as eventdate, origin.userid as userid\n" + + "from (\n" + + " select view2.eventdate as eventdate, view2.userid as userid \n" + + " from testDb.view2 view2 \n" + + " where view2.eventdate >=\"2020-01-12\" and view2.eventdate <= \"2020-01-14\"\n" + + ") origin" + ); + ArrayList<Long> selectedPartitionIds + = Lists.newArrayList(20200112L, 20200113L, 20200114L); + List<ScanNode> scanNodes = Lists.newArrayList(createEventScanNode(selectedPartitionIds)); + CacheAnalyzer ca = new CacheAnalyzer(context, parseStmt, scanNodes); + ca.checkCacheModeForNereids(1579053661000L); //2020-1-15 10:01:01 + Assert.assertEquals(ca.getCacheMode(), CacheMode.Sql); + + SqlCache sqlCache = (SqlCache) ca.getCache(); + String cacheKey = sqlCache.getSqlWithViewStmt(); + Assert.assertEquals(cacheKey, "select origin.eventdate as eventdate, origin.userid as userid\n" + + "from (\n" + + " select view2.eventdate as eventdate, view2.userid as userid \n" + + " from testDb.view2 view2 \n" + + " where view2.eventdate >=\"2020-01-12\" and view2.eventdate <= \"2020-01-14\"\n" + + ") origin" + "|select eventdate, userid FROM appevent"); + } + @Test public void testPartitionCacheKeyWithView() { Env.getCurrentSystemInfo(); @@ -1203,6 +1292,25 @@ public class PartitionCacheTest { + "eventdate<=\"2020-01-14\" GROUP BY eventdate|select eventdate, userid FROM appevent"); } + @Test + public void testSqlCacheKeyWithNestedViewForNereids() { + Env.getCurrentSystemInfo(); + StatementBase parseStmt = parseSqlByNereids("SELECT * from testDb.view4"); + ArrayList<Long> selectedPartitionIds + = Lists.newArrayList(20200112L, 20200113L, 20200114L); + List<ScanNode> scanNodes = Lists.newArrayList(createEventScanNode(selectedPartitionIds)); + CacheAnalyzer ca = new CacheAnalyzer(context, parseStmt, scanNodes); + ca.checkCacheModeForNereids(1579053661000L); //2020-1-15 10:01:01 + Assert.assertEquals(ca.getCacheMode(), CacheMode.Sql); + + SqlCache sqlCache = (SqlCache) ca.getCache(); + String cacheKey = sqlCache.getSqlWithViewStmt(); + Assert.assertEquals(cacheKey, "SELECT * from testDb.view4" + + "|select eventdate, COUNT(userid) FROM view2 " + + "WHERE eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate" + + "|select eventdate, userid FROM appevent"); + } + @Test public void testCacheLocalViewMultiOperand() { Env.getCurrentSystemInfo(); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org