PolarDB-X的XPlan索引选择

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 对于数据库来说,正确的选择索引是基本的要求,选错索引轻则导致查询缓慢,重则导致数据库整体不可用。PolarDB-X存在多种不同的索引,局部索引、全局索引、列存索引、归档表索引。本文主要介绍一种CN上的局部索引算法:XPlan索引选择。

文章来源:PolarDB-X知乎号
作者:升雨

前言

对于数据库来说,正确的选择索引是基本的要求,选错索引轻则导致查询缓慢,重则导致数据库整体不可用。PolarDB-X存在多种不同的索引,局部索引、全局索引列存索引归档表索引

局部索引就是单机数据库上常用的索引,目的是避免全表扫描。

全局索引是分布式数据库为了避免全分片扫描,冗余一份数据,采用与主表不同分区键的索引表。

列存索引是主表的列存副本,提供HTAP能力。

归档表索引是归档表上的列布隆过滤器,为归档表提供一定的TP查询能力。

本文主要介绍一种CN上的局部索引算法:XPlan索引选择。

什么是XPlan

PolarDB-X包含计算节点(CN)和数据节点(DN),CN负责SQL解析、优化和执行,DN节负责数据的持久化,CN与DN之间通过RPC通信。DN 100%兼容Mysql,也是作为PolarDB-X标准版进行售卖的。

CN与DN之间RPC通信的内容其实就是标准的SQL,CN会将解析优化好的语法树转成SQL传给DN重新解析、优化。对比起来,将CN的语法树直接传给DN执行听起来就更优[1]。

但这样其实不一定好,主要原因是作为存算分离的架构,数据都在DN上,DN可以直接在数据上进行index dive,而CN的统计信息是采样出来的静态数据,更新不及时,所以基数估计比不上DN精确,导致索引选择准确度不如DN,在很多场景下节省的DN解析优化的消耗远不如选错索引的后果。

但对于用户核心的点查场景,这样的CN优化一遍DN再优化一遍的流程就会成为瓶颈,所以PolarDB-X提供XPlan机制:对于点查场景,直接传输执行计划交给DN执行。

这样的定位说明XPlan不是必须的能力,而是锦上添花的能力。目前XPlan的适用范围被限定为单张表的DQL,只支持Scan、Filter和Project算子。

XPlan在Sysbench点查上有10%以上的提升,但线上在用户的真实场景下XPlan索引错选导致的慢查询问题频发。对于PolarDB-X来说,选错索引有两种可能:基数估计错误和执行计划缓存下的倾斜索引。

基数估计错误的三个常见原因统计信息缺失、倾斜数据和关联列,学术界、工业界研究了几十年都无法解决[2]。这些问题虽然无法解决,但是很容易检测到,PolarDB-X基本策略是检测到这些问题就禁用XPlan,交给DN做局部索引选择。同样发现索引错选也是容易的。通过预先和事后的检测,希望尽量减少XPlan错选概率。

PolarDB-X的优化器与索引选择

下图是一条sql过PolarDB-X优化器的大致过程:经过RBO和CBO后生成最好的单机执行计划,并基于CBO产生的最优执行计划的代价判断当前查询是否为AP查询,如果不是AP查询则直接构造单机执行计划,否则进一步考虑是否可以走列存索引。

无法走列存索引则基于最优单机执行计划插入shuffle算子构造分布式执行计划,否则将基于列存索引构造最优分布式执行计划。
image.png

局部索引、全局索引、归档表索引选择都在CBO里,局部索引选择影响的是Logicalview算子的IO代价,全局索引选择会将扫描主表的执行计划替换为全局索引回表,归档表索引选择可以将过滤条件复杂无法走索引的归档表扫描替换为多个简单走索引的归档表扫描。列存索引选择是利用列存对AP查询重新生成最优的分布式执行计划。

XPlan索引选择则是在单机优化器的最后对logicalview中进行索引选择。这与CBO里的局部索引选择不同,CBO里的局部索引选择只影响Logicalview算子的IO代价进而影响整个执行计划的代价,是CN基于自己的统计信息模拟DN做索引选择的过程,并不是DN真正使用的索引,只有XPlan会指定DN的索引。

PolarDB-X的执行计划缓存与倾斜值问题

PolarDB-X的执行计划获取大致逻辑如下

getPlan(String sql) 
    if PlanCache doesn't contain sql :
        PlanCache.put(sql, getPlanByOptimizer(sql))
    Plan =  PlanCache.get(sql)
    if PlanManager contiain sql :
        Plan = PlanManager.choose(sql)
    return Plan

所有的执行计划都会缓存在PlanCache中,如果PlanManager中有执行计划,则由PlanManager选择代价最低的执行计划。

这篇文章提及了Optimize Once和Optimize Always的概念,PolarDB-X采用的理念就是Optimize Once,尽量少进入优化器,主要的考量是PolarDB-X的优化器结构相当复杂,如果采用Optimize Always,优化器的耗时在高并发tp的查询中代价将无法忽视。

这里回顾一下Parameterized Queries的常见问题,考虑以下场景

create table hot_select (
    id int not null,
    c_int int,
    c_varchar varchar(20),
    PRIMARY KEY (`id`),
    KEY i_int(c_int),
    KEY i_varchar(c_varchar)
)

select * from hot_select where c_int = 1 and c_varchar = 'a';
select * from hot_select where c_int = 2 and c_varchar = 'a';

若满足c_int = 1的数据有1行,满足c_varchar = 'a'的数据有100行,满足c_int = 2有10000000行,则第一条查询应该走索引i_int,第二条查询应该走索引i_varchar。

但两条查询共用了同一个sql模版,同一个sql模版只会Optimize Once,这两条sql都只会走i_int,导致第二条查询事实上走错了索引。

这个问题学术界已经提出了很多解决方案[3],PolarDB-X之前已经在线上验证过论文里面的部分方案,设计了下图所示的一套反馈和演化的机制,由于执行计划飘忽不定导致rt不稳定,最后导致反馈演化功能被关闭。TiDB也做过类似的尝试,也是强制关闭的状态。
image.png

基于大部分学术界方案生产上不可用的事实和XPlan的锦上添花定位,Xplan索引选择的设计都以不负优化为前提,PolarDB-X采取的方案有点类似于[4],不同点在于XPlan会考虑期望基数,而是最大基数。

当然同样的问题也出现在全局索引选择上,但是由于全局索引选择的必要性,XPlan的方案并不适用,PolarDB-X有一套不同的方案来处理全局索引的倾斜值问题,在后续文章会进一步展开。

XPlan索引选择算法

XPlan核心问题有两个:如何选择索引以及如何进行执行计划传输和执行。执行计划传输和执行的大致逻辑如下图所示:在算子树上将filter尽量下推,用filter-XplanScan的pattern进行索引选择并记录到XplanScan中,基于算子树填充protobuf,利用私有协议传输给DN解析出来后直接对Innodb数据进行读取和过滤。

由于本文的主旨是XPlan索引选择而不是XPlan,这个部分不再展开,后面主要介绍如何进行XPlan的索引选择。
image.png

XPlan索引选择会尽量减少错选的概率,具体流程下图所示: 首先检查当前表的统计信息是否过期,由于统计信息可能因为各种原因无法自动更新,没有统计信息的索引选择就是乱猜,所以统计系信息过期之后会禁用XPlan,有个小优化是pk、uk的查询不受此影响。

统计信息过期的时限是7天,内核每天都会自动检查并收集3天未更新的统计信息,并在完成后再次检查统计信息,依然存在超过3天未更新的表则会发出内核报警。这个判断会减少统计信息缺失导致的基数估计错误。 第二步是过滤可能的倾斜索引,统计信息模块提供能力检查给定的列集合是否存在倾斜值,倾斜列的索引不会被XPlan使用。

这个过滤会减少Plan Cache导致的倾斜值问题。关联列估算错误一般是由于列间独立性假设的选择率迭乘导致基数估计过小,由于倾斜列被过滤,也不会出现关联列导致的基数估计过小。 第三步利用基数估计模块挑选选择率最好的索引,只有足够好的索引才可以走XPlan。

由于XPlan是Robust Query Optimization而不会选最好的索引,所以可能选不出好索引,这种情况下也会直接禁用XPlan。 最后将选择出的索引记录到XplanScan中,到此XPlan的索引选择就完成了。
image.png

再考虑一下之前的例子,由于c_int存在倾斜,XPlan不会再选择i_int而是会选择i_varchar,从而避免了倾斜值问题。

create table hot_select (
    id int not null,
    c_int int,
    c_varchar varchar(20),
    PRIMARY KEY (`id`),
    KEY i_int(c_int),
    KEY i_varchar(c_varchar)
)

select * from hot_select where c_int = 1 and c_varchar = 'a';
select * from hot_select where c_int = 2 and c_varchar = 'a';

倾斜值判断

倾斜值也就是所谓的skew data,在XPlan的场景下,只需要考虑所有索引的前缀列的组合是否有倾斜。 PolarDB-X的采样对于一张表会采出10万行数据,采样出来的频率大于5且频率/采样率大于1万就会被判断成倾斜值。

这个倾斜值判断的逻辑有改进的空间,且对抗sample的稳定性也不够强,但目前来说还是能够取得预期的效果。 那么算法就很简单了,穷举n个索引的所有前缀列,判断其在sample出的10万行中最大频率是否满足上述条件即可。若索引平均列数为m,则时间复杂度为O(1e5*nm),这个时间可以忽略不计了。

当然还有更细的优化,比如倾斜列的前缀一定是倾斜列,更大的列集合优先判断供后续剪枝之类的,不再赘述。 额外提一句PolarDB-X采样采用的是block sampling[5],在Innodb的主键上Random Walk出一些page,对于主键是天然倾斜的(特别是复合主键),所以主键的前缀列不会做倾斜值判断。

回退机制与可观测性

鉴于DN的index dive能力对于单张表的估算有更好的表现,PolarDB-X选择的兜底策略是DN返回XPlan在Innodb上扫描的行数,CN一旦发现XPlan在索引上扫描的行数超出阈值,则关闭当前sql模版的XPlan,并发出报警。

后续12小时内对应sql模版都不会再走XPlan。这个简单的机制对于只有Plan Cache的数据库也同样有效:发现Plan Cache的查询出现异常慢的情况,可以对这个模版禁用Plan Cache。
image.png

PolarDB-X支持explain execute语法查看DN物理索引。对于XPlan,explain execute会将XPlan的上下文一直传递到执行器下发物理sql之前将其拦截,否则会在XPlan的上下文中设置无法XPlan并走回正常物理sql路径。

由于回退机制的存在,explain execute可能与线上发生问题的状态不一样,排查就会变得比较困难,所以在日志中会记录每个XPlan走的索引及在Innodb上扫描行数。

线上效果

下图是最近半个月不同版本实例XPlan报警的日平均发生率。
image.png

在优化版本XPlan索引选择逻辑改变之后,每天实例出现XPlan选错索引的概率从5%降到了0.1%,下降为原本的1/50。注意老版本的XPlan选错索引后用户可以关闭XPlan,所以真实的错选概率只会更高。

报警率概率下降的主因并不是优化器能选择对的索引了,而是优化器能不选择不对的索引了。

总结

本文详细介绍了PolarDB-X对于点查场景的专门优化XPlan的索引选择方案。

包括PolarDB-X的优化器架构和其中涉及的多种索引选择、XPlan面临的索引错选问题和其中的基数估计错误、执行计划缓存机制导致的倾斜值问题,针对性设计了一个能预先检测避免错选的算法,并提供监控报警机制、错选后的兜底回退机制以及良好的可观测性,显著降低了XPlan索引错选的概率。

当然XPlan的普适性、倾斜值判断的稳定性、关联列估算能力等都可以做进一步的优化。

引用

[1] Assembling a Query Engine From Spare Parts https://www.firebolt.io/content/firebolt-vldb-cdms-2022

[2] Efficient Query Re-optimization with Judicious Subquery Selections https://arxiv.org/pdf/2202.12535.pdf

[3] Robust Query Optimization Methods With Respect to Estimation Errors: A Survey https://dl.acm.org/doi/10.1145/2854006.2854012

[4] Towards a Robust Query Optimizer: A Principled and Practical Approach https://dl.acm.org/doi/10.1145/1066157.1066172

[5] A Survey of Data Partitioning and Sampling Methods to Support Big Data Analysis https://ieeexplore.ieee.org/document/9007871


数据库PolarDB-X新人入门一站式页面,快速体验集中分布式一体化新特性!

云原生数据库PolarDB分布式版新人入门

相关实践学习
快速体验PolarDB开源数据库
本实验环境已内置PostgreSQL数据库以及PolarDB开源数据库:PolarDB PostgreSQL版和PolarDB分布式版,支持一键拉起使用,方便各位开发者学习使用。
相关文章
|
4月前
|
存储 缓存 负载均衡
【PolarDB-X 技术揭秘】Lizard B+tree:揭秘分布式数据库索引优化的终极奥秘!
【8月更文挑战第25天】PolarDB-X是阿里云的一款分布式数据库产品,其核心组件Lizard B+tree针对分布式环境优化,解决了传统B+tree面临的数据分片与跨节点查询等问题。Lizard B+tree通过一致性哈希实现数据分片,确保分布式一致性;智能分区实现了负载均衡;高效的搜索算法与缓存机制降低了查询延迟;副本机制确保了系统的高可用性。此外,PolarDB-X通过自适应分支因子、缓存优化、异步写入、数据压缩和智能分片等策略进一步提升了Lizard B+tree的性能,使其能够在分布式环境下提供高性能的索引服务。这些优化不仅提高了查询速度,还确保了系统的稳定性和可靠性。
100 5
|
5月前
|
SQL 关系型数据库 分布式数据库
PolarDB产品使用问题之相同的SQL语句在不同时间执行EXPLAIN计划显示出不同的索引类型,是什么原因
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
PolarDB产品使用问题之相同的SQL语句在不同时间执行EXPLAIN计划显示出不同的索引类型,是什么原因
|
4月前
|
C# UED 定位技术
WPF控件大全:初学者必读,掌握控件使用技巧,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,控件是实现用户界面交互的关键元素。WPF提供了丰富的控件库,包括基础控件(如`Button`、`TextBox`)、布局控件(如`StackPanel`、`Grid`)、数据绑定控件(如`ListBox`、`DataGrid`)等。本文将介绍这些控件的基本分类及使用技巧,并通过示例代码展示如何在项目中应用。合理选择控件并利用布局控件和数据绑定功能,可以提升用户体验和程序性能。
83 0
|
5月前
|
SQL 关系型数据库 分布式数据库
PolarDB产品使用问题之如何实现在线上加索引,并且不会锁表
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
5月前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用问题之Join评估的行数比索引的基数小,是什么导致的
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
6月前
|
关系型数据库 MySQL 分布式数据库
PolarDB产品使用问题之mysql迁移后查询不走索引了,该如何解决
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
6月前
|
运维 关系型数据库 分布式数据库
PolarDB产品使用问题之列存索引的原理是什么
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
6月前
|
存储 算法 数据处理
惊人!PolarDB-X 存储引擎核心技术的索引回表优化如此神奇!
【6月更文挑战第11天】PolarDB-X存储引擎以其索引回表优化技术引领数据库发展,提升数据检索速度,优化磁盘I/O,确保系统在高并发场景下的稳定与快速响应。通过示例代码展示了在查询操作中如何利用该技术高效获取结果。索引回表优化具备出色性能、高度可扩展性和适应性,为应对大数据量和复杂业务提供保障,助力企业与开发者实现更高效的数据处理。
74 3
|
6月前
|
SQL 关系型数据库 分布式数据库
PolarDB产品使用问题之如何查看SQL语句使用的是行索引还是列索引
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
7月前
|
安全 druid Java
Seata 1.8.0 正式发布,支持达梦和 PolarDB-X 数据库
Seata 1.8.0 正式发布,支持达梦和 PolarDB-X 数据库
Seata 1.8.0 正式发布,支持达梦和 PolarDB-X 数据库

相关产品

  • 云原生分布式数据库 PolarDB-X
  • 下一篇
    DataWorks