Starrocks 的 ShortCircuit短路徑

背景

本文基于 Starrocks 3.3.5
本文主要來探索一下Starrocks在FE端怎么實現 短路徑,從而加速點查查詢速度。
在用戶層級需要設置 enable_short_circuit 為true

分析

數據流:
直接到StatementPlanner.createQueryPlan方法:

...
OptExpression root = ShortCircuitPlanner.checkSupportShortCircuitRead(logicalPlan.getRoot(), session);
...
optimizedPlan = optimizer.optimize(session,root,mvTransformerContext,stmt,new PhysicalPropertySet(),new ColumnRefSet(logicalPlan.getOutputColumn()),columnRefFactory);

首先是通過ShortCircuitPlanner.checkSupportShortCircuitRead來判斷該SQL是不是支持短路徑查詢:

 public static OptExpression checkSupportShortCircuitRead(OptExpression root, ConnectContext connectContext) {if (!connectContext.getSessionVariable().isEnableShortCircuit()) {root.setShortCircuit(false);return root;}boolean supportShortCircuit = root.getOp().accept(new LogicalPlanChecker(), root, null);if (supportShortCircuit && OperatorType.LOGICAL_LIMIT.equals(root.getOp().getOpType())) {root = root.getInputs().get(0);}root.setShortCircuit(supportShortCircuit);return root;}
  • 通過isEnableShortCircuit也就是enable_short_circuit(默認是false) 來判斷是否支持短路徑查詢
  • 通過visitor LogicalPlanChecker來判斷SQL本身是否支持短路徑查詢
    通過 LogicalPlanChecker 實現看到,目前只支持 Scan Project Filter Limit 操作:
     public static class LogicalPlanChecker extends BaseLogicalPlanChecker {...@Overridepublic Boolean visitLogicalFilter(OptExpression optExpression, Void context) {...return visitChild(optExpression, context);}@Overridepublic Boolean visitLogicalProject(OptExpression optExpression, Void context) {...return visitChild(optExpression, context);}@Overridepublic Boolean visitLogicalLimit(OptExpression optExpression, Void context) {...return visitChild(optExpression, context);}@Overridepublic Boolean visitLogicalTableScan(OptExpression optExpression, Void context) {return createLogicalPlanChecker(optExpression, allowFilter, allowLimit, allowProject,allowSort, predicate, orderByColumns, limit).visitLogicalTableScan(optExpression, context);}protected static boolean isPointScan(Table table,List<String> keyColumns,List<ScalarOperator> conjuncts,ShortCircuitContext shortCircuitContext) {Map<String, PartitionColumnFilter> filters = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);filters.putAll(ColumnFilterConverter.convertColumnFilter(conjuncts, table));if (keyColumns == null || keyColumns.isEmpty()) {return false;}long cardinality = 1;for (String keyColumn : keyColumns) {if (filters.containsKey(keyColumn)) {PartitionColumnFilter filter = filters.get(keyColumn);if (filter.getInPredicateLiterals() != null) {cardinality *= filter.getInPredicateLiterals().size();// TODO(limit operator place fe)if (cardinality > MAX_RETURN_ROWS ||(shortCircuitContext.getMaxReturnRows() != 0 && cardinality != 1)) {return false;}} else if (!filter.isPoint()) {return false;}} else {return false;}}return true;}}}
    
    • 直接看visitLogicalTableScan這個方法
      只有是存算一體的,也就是LogicalOlapScanOperator實例,才會有短路徑查詢,最終會走到ShortCircuitPlannerHybrid.LogicalPlanChecker.visitLogicalTableScan方法
      public Boolean visitLogicalTableScan(OptExpression optExpression, Void context) {LogicalScanOperator scanOp = optExpression.getOp().cast();Table table = scanOp.getTable();if (!(table instanceof OlapTable) || !(KeysType.PRIMARY_KEYS.equals(((OlapTable) table).getKeysType()))) {return false;}for (Column column : table.getFullSchema()) {if (IDictManager.getInstance().hasGlobalDict(table.getId(), column.getColumnId())) {return false;}}List<String> keyColumns = ((OlapTable) table).getKeyColumns().stream().map(Column::getName).collect(Collectors.toList());List<ScalarOperator> conjuncts = Utils.extractConjuncts(predicate);return isPointScan(table, keyColumns, conjuncts, shortCircuitContext);}
      
      • 首先必須滿足 是主鍵模型
      • 再次是 必須滿足SQL 查詢的表和字段沒有全局字典
      • 最后 判斷是不是點查
        滿足:1. 過濾條件要么是IN,要么是=
        2. 如果是IN的話,IN中的項不能超過2024個
        3. 必須包含所有的主鍵(可以額外包含其他的非主鍵)
  • 如果確定可以走短路徑的話,則設置root.setShortCircuit(true),否則為false

再次進行計劃級別的優化 optimizer.optimize:
這里會調用optimizeByCost方法,到調用 rewriteAndValidatePlan方法:

 private OptExpression rewriteAndValidatePlan(OptExpression tree,TaskContext rootTaskContext) {OptExpression result = logicalRuleRewrite(tree, rootTaskContext);OptExpressionValidator validator = new OptExpressionValidator();validator.validate(result);// skip memoif (result.getShortCircuit()) {result = new OlapScanImplementationRule().transform(result, null).get(0);result.setShortCircuit(true);}return result;}

ShortCircuit 短路徑涉及到的有兩方面:

  1. logicalRuleRewrite中 ruleRewriteForShortCircuit
        private Optional<OptExpression> ruleRewriteForShortCircuit(OptExpression tree, TaskContext rootTaskContext) {Boolean isShortCircuit = tree.getShortCircuit();if (isShortCircuit) {deriveLogicalProperty(tree);ruleRewriteIterative(tree, rootTaskContext, RuleSetType.SHORT_CIRCUIT_SET);ruleRewriteOnlyOnce(tree, rootTaskContext, new MergeProjectWithChildRule());OptExpression result = tree.getInputs().get(0);result.setShortCircuit(true);return Optional.of(result);}return Optional.empty();}
    

這里會專門針對于shortCircuit做一些規則優化:

new PruneTrueFilterRule(),
new PushDownPredicateProjectRule(),
PushDownPredicateScanRule.OLAP_SCAN,
new CastToEmptyRule(),
new PruneProjectColumnsRule(),
PruneScanColumnRule.OLAP_SCAN,
new PruneProjectEmptyRule(),
new MergeTwoProjectRule(),
new PruneProjectRule(),
new PartitionPruneRule(),
new DistributionPruneRule();
 new MergeProjectWithChildRule()

以上規則只是在project以及 常量優化,以及更好的過濾數據的層級進行了優化,免去了一般性的規則過濾. 正如primary_key_table所說,由于primary key模型使得謂詞下推成為了可能。

  1. OlapScanImplementationRule().transform
    這個也是在該SQL能夠進行短路徑的情況下,才會走到的數據流
    這一步的作用主要是把邏輯的scan轉換為物理的scan

經過了以上兩步以后,就直接返回了,也不會進入到memo的CBO優化。
至此 FE端 短路徑的 優化就結束了,接下來就是生成物理計劃了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/79360.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79360.shtml
英文地址,請注明出處:http://en.pswp.cn/web/79360.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Oracle非歸檔模式遇到文件損壞怎么辦?

昨天夜里基地夜班的兄弟&#xff0c;打電話說有個報表庫連不上了&#xff0c;趕緊起來連上VPN查看一下&#xff0c;看到實例宕機了&#xff0c;先趕緊startup起來。 1.查看報錯信息 環境介紹&#xff1a;Redhat 6.9 Oracle 11.2.0.4 No Archive Mode 查看alert log 關鍵報…

關于一些平時操作系統或者軟件的步驟轉載

關于一些平時操作系統或者軟件的步驟轉載 關于python環境搭建 關于Ubuntu 1. 雙系統之Ubuntu快速卸載 2. VMware安裝Ubuntu虛擬機實現COpenCV代碼在虛擬機下運行教程 3. ubuntu 下 opencv的安裝以及配置&#xff08;親測有效&#xff09; 4. Ubuntu將c編譯成.so文件并測試 5…

hz2新建Keyword頁面

新建一個single-keywords.php即可&#xff0c;需要篩選項再建taxonomy-knowledge-category.php 參考&#xff1a;https://www.tkwlkj.com/customize-wordpress-category-pages.html WordPress中使用了ACF創建了自定義產品分類products&#xff0c;現在想實現自定義產品分類下的…

VRRP協議-IP地址冗余配置

有兩個服務器172.16.42.1和172.16.42.121&#xff0c;通過VRRP協議使兩臺設備共用一個虛擬地址172.16.42.100&#xff0c;當 172.16.42.1 可用時&#xff0c;它會作為主路由器使用虛擬 IP 地址&#xff1b;當它不可用時&#xff0c;172.16.42.121 會接管虛擬 IP 地址&#xff0…

21、DeepSeekMath論文筆記(GRPO)

DeepSeekMath論文筆記 0、研究背景與目標1、GRPO結構GRPO結構PPO知識點**1. PPO的網絡模型結構****2. GAE&#xff08;廣義優勢估計&#xff09;原理****1. 優勢函數的定義**2.GAE&#xff08;廣義優勢估計&#xff09; 2、關鍵技術與方法3、核心實驗結果4、結論與未來方向關鍵…

卡爾曼濾波算法(C語言)

此處感謝華南虎和互聯網的眾多大佬的無償分享。 入門常識 先簡單了解以下概念&#xff1a;疊加性&#xff0c;齊次性。 用大白話講&#xff0c;疊加性&#xff1a;多個輸入對輸出有影響。齊次性&#xff1a;輸入放大多少倍&#xff0c;輸出也跟著放大多少倍 卡爾曼濾波符合這…

SolidWork-2023 鼠標工程

地址 https://github.com/MartinxMax/SW2023-Project/tree/main/mouse 鼠標

vue 組件函數式調用實戰:以身份驗證彈窗為例

通常我們在 Vue 中使用組件&#xff0c;是像這樣在模板中寫標簽&#xff1a; <MyComponent :prop"value" event"handleEvent" />而函數式調用&#xff0c;則是讓我們像調用一個普通 JavaScript 函數一樣來使用這個組件&#xff0c;例如&#xff1a;…

Vite Proxy配置詳解:從入門到實戰應用

Vite Proxy配置詳解&#xff1a;從入門到實戰應用 一、什么是Proxy代理&#xff1f; Proxy&#xff08;代理&#xff09;是開發中常用的解決跨域問題的方案。Vite內置了基于http-proxy的代理功能&#xff0c;可以輕松配置API請求轉發。 二、基礎配置 在vite.config.js中配置…

圖像畫質算法記錄(前言)

一、背景介紹 本篇主要是對圖像畫質增強相關&#xff0c;進行簡單整理和記錄。 二、整體流程 整體效果主要受到兩部分影響&#xff1a; 1、前端isp處理。 2、后端畫質增強。 三、isp常規流程 可以參考&#xff1a;劉斯寧&#xff1a;Understanding ISP Pipeline 四、后端畫質…

Qt 中信號與槽(signal-slot)機制支持 多種連接方式(ConnectionType)

Qt 中信號與槽&#xff08;signal-slot&#xff09;機制支持 多種連接方式&#xff08;ConnectionType&#xff09; Qt 中信號與槽&#xff08;signal-slot&#xff09;機制支持 多種連接方式&#xff08;ConnectionType&#xff09;&#xff0c;用于控制信號發出后如何調用槽…

卷積神經網絡實戰(4)代碼詳解

目錄 一、導包 二、數據準備 1.數據集 2. 標準化轉換(Normalize) 3.設置dataloader 三、定義模型 四、可視化計算圖&#xff08;不重要&#xff09; 五、評估函數 六、Tensorboard 一、導包 import matplotlib as mpl import matplotlib.pyplot as plt %matplotlib i…

深入解析進程地址空間:從虛擬到物理的奇妙之旅

深入解析進程地址空間&#xff1a;從虛擬到物理的奇妙之旅 前言 各位小伙伴&#xff0c;還記得我們之前探討的 fork 函數嗎&#xff1f;當它返回兩次時&#xff0c;父子進程中同名變量卻擁有不同值的現象&#xff0c;曾讓我們驚嘆于進程獨立性與寫時拷貝的精妙設計。但你是否…

opencv處理圖像(二)

接下來進入到程序線程設計部分 我們主線程負責圖形渲染等操作&#xff0c;OpenGL的限制&#xff0c;opencv技術對傳入圖像加以處理&#xff0c;輸出預期圖像給主線程 QThread 我之前也是在想給opencv開一個專門的線程&#xff0c;但經過了解有幾個弊端&#xff0c;第一資源浪…

學習threejs,使用Physijs物理引擎

&#x1f468;??? 主頁&#xff1a; gis分享者 &#x1f468;??? 感謝各位大佬 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;??? 收錄于專欄&#xff1a;threejs gis工程師 文章目錄 一、&#x1f340;前言1.1 ??Physijs 物理引擎1.1.1 ??…

ARCGIS PRO DSK 選擇坐標系控件(CoordinateSystemsControl )的調用

在WPF窗體上使用 xml&#xff1a;加入空間命名引用 xmlns:mapping"clr-namespace:ArcGIS.Desktop.Mapping.Controls;assemblyArcGIS.Desktop.Mapping" 在控件區域加入&#xff1a; <mapping:CoordinateSystemsControl x:Name"CoordinateSystemsControl&q…

LangGraph(三)——添加記憶

目錄 1. 創建MemorySaver檢查指針2. 構建并編譯Graph3. 與聊天機器人互動4. 問一個后續問題5. 檢查State參考 1. 創建MemorySaver檢查指針 創建MemorySaver檢查指針&#xff1a; from langgraph.checkpoint.memory import MemorySavermemory MemorySaver()這是位于內存中的檢…

深入理解Mysql

BufferPool和Changebuffer是如何加快讀寫速度的? BufferPool 在Mysql啟動的時候 Mysql會申請連續的空間來存儲BufferPool 每個頁16kb 當控制塊不足以存儲信息的時候就會向后申請一個新的頁 每個控制塊都對應了一個緩存頁 控制塊占chunk的百分之5左右 LRU鏈表 Changebuffer …

Python核心編程深度解析:作用域、遞歸與匿名函數的工程實踐

引言 Python作為現代編程語言的代表&#xff0c;其作用域管理、遞歸算法和匿名函數機制是構建高質量代碼的核心要素。本文基于Python 3.11環境&#xff0c;結合工業級開發實踐&#xff0c;深入探討變量作用域的內在邏輯、遞歸算法的優化策略以及匿名函數的高效應用&#xff0c…

《用MATLAB玩轉游戲開發》貪吃蛇的百變玩法:從命令行到AI對戰

《用MATLAB玩轉游戲開發&#xff1a;從零開始打造你的數字樂園》基礎篇&#xff08;2D圖形交互&#xff09;-&#x1f40d; 貪吃蛇的百變玩法&#xff1a;從命令行到AI對戰 &#x1f3ae; 歡迎來到這篇MATLAB貪吃蛇編程全攻略&#xff01;本文將帶你從零開始&#xff0c;一步步…