如何利用OceanBase v4.2的 Runtime Filter提升查询效率

OceanBase数据库中可使用Hash Join联接算法,这种算法可以依据某些字段对两个表进行等值匹配连接。然而,当涉及连接的表(特别是作为Probe Table的表)数据量较大时,Hash Join的性能会显著下降。针对这一问题,通常采取的方法是运用Runtime Filter来提升查询效率。

本文将详细阐述OceanBase中的Runtime Filter功能,并探讨在4.2版本中该功能的优化细节。

OceanBase中的Runtime Filter能力

Runtime Filter是一种用于优化Hash Join性能的技术,它可以通过减少Hash Join需要Probe的数据量来提高查询的效率。比如,在星形连接的多张维度表和事实表Join的场景中,Runtime Filter是一个非常有效的优化手段。本质上,Runtime Filter是一类过滤器,它可以利用Hash Join的Build过程构建一个轻量的Filter,然后将Filter广播发送给参与Probe的大表,Probe Table可以使用多个Runtime Filter提前在存储层过滤数据,减少真正参与Hash Join及网络传输的数据,从而提高查询效率。

Runtime Filter的数据结构有Bloom Filter、In Filter、Range Filter三种,始终贯穿Runtime Filter的使用类别。下面通过Runtime Filter的各类别来说明Runtime Filter的作用是使用场景。

1、Runtime Filter跨机传输需求场景

首先,按照是否需要跨机传输来看,Runtime Filter可以分为Local和Global两类,无论是Local还是Global,都可以使用这三种结构的Runtime Filter。我们通过explain可以显示当前计划中的Runtime Filter。计划中和Runtime Filter相关的算子有:

JOIN FILTER CREATE: 表示创建 Runtime Filter 的算子,其后面的NAME区分了同一个计划中的多个Runtime Filter
JOIN FILTER USE: 表示使用 Runtime Filter 的算子,拥有相同NAME的JOIN FILTER CREATE和JOIN FILTER USE是一对。由于filter下推逻辑的存在,真正使用Runtime Filter算子一般是其下方的Table Scan算子。PART JOIN FILTER CREATE:表示创建 Part Join Filter 的算子, 其后面的NAME区分了同一个计划中的多个Runtime Filter
PX PARTITION HASH JOIN-FILTER: 表示使用 Part Join Filter 的算子,拥有相同NAME的PART JOIN FILTER CREATE和PX PARTITION HASH JOIN-FILTER是一对。

(1)Local Runtime Filter

Local Runtime Filter意味着Runtime Filter无需经历网络传输,构建的Filter只需要在本地节点计算过滤,这通常适用于Hash Join Probe侧没有Shuffle的场景。下面为Local Runtime Filter计划:

obclient> create table tt1(v1 int, v2 int) partition by hash(v1) partitions 5;
obclient> create table tt2(v1 int, v2 int) partition by hash(v1) partitions 5;
obclient> explain select /*+ px_join_filter(tt2) parallel(4) */ * from tt1 join tt2 on tt1.v1=tt2.v1;
+------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                         |
+------------------------------------------------------------------------------------------------------------------------------------+
| ==============================================================                                                                     |
| |ID|OPERATOR                  |NAME    |EST.ROWS|EST.TIME(us)|                                                                     |
| --------------------------------------------------------------                                                                     |
| |0 |PX COORDINATOR            |        |1       |7           |                                                                     |
| |1 |└─EXCHANGE OUT DISTR      |:EX10000|1       |6           |                                                                     |
| |2 |  └─PX PARTITION ITERATOR |        |1       |6           |                                                                     |
| |3 |    └─HASH JOIN           |        |1       |6           |                                                                     |
| |4 |      ├─JOIN FILTER CREATE|:RF0000 |1       |3           |                                                                     |
| |5 |      │ └─TABLE FULL SCAN |tt2     |1       |3           |                                                                     |
| |6 |      └─JOIN FILTER USE   |:RF0000 |1       |4           |                                                                     |
| |7 |        └─TABLE FULL SCAN |tt1     |1       |4           |                                                                     |
| ==============================================================                                                                     |
| Outputs & filters:                                                                                                                 |
| -------------------------------------                                                                                              |
|   0 - output([INTERNAL_FUNCTION(tt1.v1, tt1.v2, tt2.v1, tt2.v2)]), filter(nil), rowset=256                                         |
|   1 - output([INTERNAL_FUNCTION(tt1.v1, tt1.v2, tt2.v1, tt2.v2)]), filter(nil), rowset=256                                         |
|       dop=4                                                                                                                        |
|   2 - output([tt1.v1], [tt2.v1], [tt2.v2], [tt1.v2]), filter(nil), rowset=256                                                      |
|       partition wise, force partition granule                                                                                      |
|   3 - output([tt1.v1], [tt2.v1], [tt2.v2], [tt1.v2]), filter(nil), rowset=256                                                      |
|       equal_conds([tt1.v1 = tt2.v1]), other_conds(nil)                                                                             |
|   4 - output([tt2.v1], [tt2.v2]), filter(nil), rowset=256                                                                          |
|       RF_TYPE(in, range, bloom), RF_EXPR[tt2.v1]                                                                                   |
|   5 - output([tt2.v1], [tt2.v2]), filter(nil), rowset=256                                                                          |
|       access([tt2.v1], [tt2.v2]), partitions(p[0-4])                                                                               |
|       is_index_back=false, is_global_index=false,                                                                                  |
|       range_key([tt2.__pk_increment]), range(MIN ; MAX)always true                                                                 |
|   6 - output([tt1.v1], [tt1.v2]), filter(nil), rowset=256                                                                          |
|   7 - output([tt1.v1], [tt1.v2]), filter([RF_IN_FILTER(tt1.v1)], [RF_RANGE_FILTER(tt1.v1)], [RF_BLOOM_FILTER(tt1.v1)]), rowset=256 |
|       access([tt1.v1], [tt1.v2]), partitions(p[0-4])                                                                               |
|       is_index_back=false, is_global_index=false, filter_before_indexback[false,false,false],                                      |
|       range_key([tt1.__pk_increment]), range(MIN ; MAX)always true                                                                 |
+------------------------------------------------------------------------------------------------------------------------------------+
32 rows in set (0.045 sec)

在计划中显示为JOIN FILTER CREATE 和 JOIN FILTER USE的这一对算子就是Runtime Filter。Name为RF0000的4号和6号算子在该计划中构建了一个Local Runtime FIlter,该Filter无需网络传播,仅在本机使用。

(2)Global Runtime FIlter

Global Runtime Filter意味着该Filter需要广播传输给多个执行节点,并且在计划形态中可以按需将Runtime Filter嵌套下压至计划中的任意位置完成过滤。相比Local Runtime Filter,由于节省的代价不仅包括SQL层投影及计算开销,还包括了网络传输,因此往往能获得不错的执行性能提升。下面为Global Runtime Filter计划:

obclient> create table t1 (C1_RAND int, C2_RAND int, C3_RAND int, C4_RAND int, C5_RAND int) partition by hash(C5_RAND) partitions 5;
obclient> create table t2 (C1_RAND int, C2_RAND int, C3_RAND int, C4_RAND int, C5_RAND int) partition by hash(C5_RAND) partitions 5;
obclient> create table t3 (C1_RAND int, C2_RAND int, C3_RAND int, C4_RAND int, C5_RAND int) partition by hash(C5_RAND) partitions 5;
obclient> explain basic select /*+ leading(a (b  c)) parallel(3) use_hash(b) use_hash(c) pq_distribute(c hash hash) px_join_filter(c a)  px_join_filter(c b) */ count(*) from t1 a, t2 b, t3 c where a.C1_RAND=b.C1_RAND and a.C2_RAND = c.C2_RAND and b.C3_RAND = c.C3_RAND;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                                                       |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ========================================================                                                                                                         |
| |ID|OPERATOR                                  |NAME    |                                                                                                         |
| --------------------------------------------------------                                                                                                         |
| |0 |SCALAR GROUP BY                           |        |                                                                                                         |
| |1 |└─PX COORDINATOR                          |        |                                                                                                         |
| |2 |  └─EXCHANGE OUT DISTR                    |:EX10003|                                                                                                         |
| |3 |    └─MERGE GROUP BY                      |        |                                                                                                         |
| |4 |      └─SHARED HASH JOIN                  |        |                                                                                                         |
| |5 |        ├─JOIN FILTER CREATE              |:RF0001 |                                                                                                         |
| |6 |        │ └─EXCHANGE IN DISTR             |        |                                                                                                         |
| |7 |        │   └─EXCHANGE OUT DISTR (BC2HOST)|:EX10000|                                                                                                         |
| |8 |        │     └─PX BLOCK ITERATOR         |        |                                                                                                         |
| |9 |        │       └─TABLE FULL SCAN         |a       |                                                                                                         |
| |10|        └─HASH JOIN                       |        |                                                                                                         |
| |11|          ├─JOIN FILTER CREATE            |:RF0000 |                                                                                                         |
| |12|          │ └─EXCHANGE IN DISTR           |        |                                                                                                         |
| |13|          │   └─EXCHANGE OUT DISTR (HASH) |:EX10001|                                                                                                         |
| |14|          │     └─PX BLOCK ITERATOR       |        |                                                                                                         |
| |15|          │       └─TABLE FULL SCAN       |b       |                                                                                                         |
| |16|          └─EXCHANGE IN DISTR             |        |                                                                                                         |
| |17|            └─EXCHANGE OUT DISTR (HASH)   |:EX10002|                                                                                                         |
| |18|              └─JOIN FILTER USE           |:RF0000 |                                                                                                         |
| |19|                └─JOIN FILTER USE         |:RF0001 |                                                                                                         |
| |20|                  └─PX BLOCK ITERATOR     |        |                                                                                                         |
| |21|                    └─TABLE FULL SCAN     |c       |                                                                                                         |
| ========================================================                                                                                                         |
| Outputs & filters:                                                                                                                                               |
| -------------------------------------                                                                                                                            |
|   0 - output([T_FUN_COUNT_SUM(T_FUN_COUNT(*))]), filter(nil), rowset=256                                                                                         |
|       group(nil), agg_func([T_FUN_COUNT_SUM(T_FUN_COUNT(*))])                                                                                                    |
|   1 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256                                                                                                          |
|   2 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256                                                                                                          |
|       dop=3                                                                                                                                                      |
|   3 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256                                                                                                          |
|       group(nil), agg_func([T_FUN_COUNT(*)])                                                                                                                     |
|   4 - output(nil), filter(nil), rowset=256                                                                                                                       |
|       equal_conds([a.C1_RAND = b.C1_RAND], [a.C2_RAND = c.C2_RAND]), other_conds(nil)                                                                            |
|   5 - output([a.C2_RAND], [a.C1_RAND]), filter(nil), rowset=256                                                                                                  |
|       RF_TYPE(in, range, bloom), RF_EXPR[a.C2_RAND]                                                                                                              |
|   6 - output([a.C2_RAND], [a.C1_RAND]), filter(nil), rowset=256                                                                                                  |
|   7 - output([a.C2_RAND], [a.C1_RAND]), filter(nil), rowset=256                                                                                                  |
|       dop=3                                                                                                                                                      |
|   8 - output([a.C1_RAND], [a.C2_RAND]), filter(nil), rowset=256                                                                                                  |
|   9 - output([a.C1_RAND], [a.C2_RAND]), filter(nil), rowset=256                                                                                                  |
|       access([a.C1_RAND], [a.C2_RAND]), partitions(p[0-4])                                                                                                       |
|       is_index_back=false, is_global_index=false,                                                                                                                |
|       range_key([a.__pk_increment]), range(MIN ; MAX)always true                                                                                                 |
|  10 - output([b.C1_RAND], [c.C2_RAND]), filter(nil), rowset=256                                                                                                  |
|       equal_conds([b.C3_RAND = c.C3_RAND]), other_conds(nil)                                                                                                     |
|  11 - output([b.C3_RAND], [b.C1_RAND]), filter(nil), rowset=256                                                                                                  |
|       RF_TYPE(in, range, bloom), RF_EXPR[b.C3_RAND]                                                                                                              |
|  12 - output([b.C3_RAND], [b.C1_RAND]), filter(nil), rowset=256                                                                                                  |
|  13 - output([b.C3_RAND], [b.C1_RAND]), filter(nil), rowset=256                                                                                                  |
|       (#keys=1, [b.C3_RAND]), dop=3                                                                                                                              |
|  14 - output([b.C1_RAND], [b.C3_RAND]), filter(nil), rowset=256                                                                                                  |
|  15 - output([b.C1_RAND], [b.C3_RAND]), filter(nil), rowset=256                                                                                                  |
|       access([b.C1_RAND], [b.C3_RAND]), partitions(p[0-4])                                                                                                       |
|       is_index_back=false, is_global_index=false,                                                                                                                |
|       range_key([b.__pk_increment]), range(MIN ; MAX)always true                                                                                                 |
|  16 - output([c.C3_RAND], [c.C2_RAND]), filter(nil), rowset=256                                                                                                  |
|  17 - output([c.C3_RAND], [c.C2_RAND]), filter(nil), rowset=256                                                                                                  |
|       (#keys=1, [c.C3_RAND]), dop=3                                                                                                                              |
|  18 - output([c.C3_RAND], [c.C2_RAND]), filter(nil), rowset=256                                                                                                  |
|  19 - output([c.C3_RAND], [c.C2_RAND]), filter(nil), rowset=256                                                                                                  |
|  20 - output([c.C2_RAND], [c.C3_RAND]), filter(nil), rowset=256                                                                                                  |
|  21 - output([c.C2_RAND], [c.C3_RAND]), filter([RF_IN_FILTER(c.C3_RAND)], [RF_RANGE_FILTER(c.C3_RAND)], [RF_BLOOM_FILTER(c.C3_RAND)], [RF_IN_FILTER(c.C2_RAND)], |
|        [RF_RANGE_FILTER(c.C2_RAND)], [RF_BLOOM_FILTER(c.C2_RAND)]), rowset=256                                                                                   |
|       access([c.C2_RAND], [c.C3_RAND]), partitions(p[0-4])                                                                                                       |
|       is_index_back=false, is_global_index=false, filter_before_indexback[false,false,false,false,false,false],                                                  |
|       range_key([c.__pk_increment]), range(MIN ; MAX)always true                                                                                                 |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
70 rows in set (0.103 sec)

5号算子对应RF0001,11号算子对应RF000,均下推到21号table full scan算子上进行过滤,此过程横跨了多个DFO,需要通过网络传输,属于Global Runtime Filter。

2、Runtime Filter生效功能场景

其次,从Runtime Filter生效的功能而言,Runtime Filter可以分为过滤连接数据的Filter和过滤分区的Filter两类。第一类为普通Runtime Filter,支持三种数据结构;第二类为Part Join Filter,当前仅支持Bloom Filter。下面重点介绍Part Join Filter。

Hash Join的执行流程是左侧数据阻塞建哈希表, 右侧逐行匹配数据。左侧建哈希表会获取左侧所有数据。如果可以获取左侧所有数据关于右侧某表的分区分布特征(按照右表的分区方式计算出左表关于右表的分区id), 那么在右侧扫描该表数据时,可以根据已统计的分区分布特征提前过滤掉不必要的分区,从而提升性能,Part Bloom Filter的引入正是为了优化这一场景。

想要在Hash Join左侧计算出按照右侧某表分区方式的具体分区,Join的连接键必须包含右侧该表的分区键,这是生成Part Bloom Filter的前提。

obclient [mysql]> create table t1(v1 int);
obclient [mysql]> create table t2(v1 int) partition by hash(v1) partitions 5;
obclient [mysql]> explain select /*+ parallel(3) leading(t1 t2) px_part_join_filter(t2)*/ * from t1 join t2 on t1.v1=t2.v1;
+-------------------------------------------------------------------------------+
| Query Plan                                                                    |
+-------------------------------------------------------------------------------+
| =======================================================================       |
| |ID|OPERATOR                           |NAME    |EST.ROWS|EST.TIME(us)|       |
| -----------------------------------------------------------------------       |
| |0 |PX COORDINATOR                     |        |1       |5           |       |
| |1 |└─EXCHANGE OUT DISTR               |:EX10001|1       |4           |       |
| |2 |  └─HASH JOIN                      |        |1       |4           |       |
| |3 |    ├─PART JOIN FILTER CREATE      |:RF0000 |1       |1           |       |
| |4 |    │ └─EXCHANGE IN DISTR          |        |1       |1           |       |
| |5 |    │   └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1       |1           |       |
| |6 |    │     └─PX BLOCK ITERATOR      |        |1       |1           |       |
| |7 |    │       └─TABLE FULL SCAN      |t1      |1       |1           |       |
| |8 |    └─PX PARTITION HASH JOIN-FILTER|:RF0000 |1       |3           |       |
| |9 |      └─TABLE FULL SCAN            |t2      |1       |3           |       |
| =======================================================================       |
| Outputs & filters:                                                            |
| -------------------------------------                                         |
|   0 - output([INTERNAL_FUNCTION(t1.v1, t2.v1)]), filter(nil), rowset=256      |
|   1 - output([INTERNAL_FUNCTION(t1.v1, t2.v1)]), filter(nil), rowset=256      |
|       dop=3                                                                   |
|   2 - output([t1.v1], [t2.v1]), filter(nil), rowset=256                       |
|       equal_conds([t1.v1 = t2.v1]), other_conds(nil)                          |
|   3 - output([t1.v1]), filter(nil), rowset=256                                |
|       RF_TYPE(bloom), RF_EXPR[t1.v1]                                          |
|   4 - output([t1.v1]), filter(nil), rowset=256                                |
|   5 - output([t1.v1]), filter(nil), rowset=256                                |
|       (#keys=1, [t1.v1]), dop=3                                               |
|   6 - output([t1.v1]), filter(nil), rowset=256                                |
|   7 - output([t1.v1]), filter(nil), rowset=256                                |
|       access([t1.v1]), partitions(p0)                                         |
|       is_index_back=false, is_global_index=false,                             |
|       range_key([t1.__pk_increment]), range(MIN ; MAX)always true             |
|   8 - output([t2.v1]), filter(nil), rowset=256                                |
|       affinitize                                                              |
|   9 - output([t2.v1]), filter(nil), rowset=256                                |
|       access([t2.v1]), partitions(p[0-4])                                     |
|       is_index_back=false, is_global_index=false,                             |
|       range_key([t2.__pk_increment]), range(MIN ; MAX)always true             |
+-------------------------------------------------------------------------------+

在计划中显示为 PART JOIN FILTER CREATE 的3号算子和 PX PARTITION HASH JOIN-FILTER的8号算子就是一对Part Join Filter,3号算子创建Part Join Filter,他会应用到8号算子中对t2表的分区进行过滤。

手动分配Runtime Filter

在默认配置下,当Join基于连接键的过滤性高于一定条件时(目前约为60%)会默认创建三种Runtime Filter数据结构:

  • In Filter,内部使用hash表进行过滤判定;
  • Range Filter,内部使用最大最小值进行过滤判定;
  • Bloom Filter,自身就是一种过滤器。

在过滤优先级上,由于In Filter具有最准的过滤性,执行器当In Filter被启用时,其他两种Filter会被自适应关闭,在执行器根据实际NDV值确定是否使用In Filter。此外,每种Filter在实际计算中会根据实时过滤性自适应Disable Filter以及重新Enable Filter。

Runtime Filter的使用场景仅限于Hash Join,当连接类型不为Hash Join时,优化器将不会分配Runtime Filter。一般情况下,优化器会自动分配Runtime Filter,如果优化器并未分配Runtime Filter,大家也可以通过hint手动分配Runtime Filter。

我们可以通过px_join_fitler以及px_part_join_filter来手动打开runtime filter/part join filter。

/*+ px_join_filter(join_right_table_name)*/
/*+ px_part_join_filter(join_right_table_name)*/

也可以通过no_px_join_filter以及px_part_join_filter来手动关闭runtime filter/part join filter。

/*+ no_px_join_filter(join_right_table_name)*/
/*+ no_px_part_join_filter(join_right_table_name)*/

需要注意的是,在并行度为1的场景下,不会分配Runtime Filter,我们需要至少指定并行度为2。

/*+ parallel(2) */

在手动分配Runtime Filter的过程中,会涉及一些系统变量,以下提供了4个系统变量用于在需要场景下调整Runtime Filter执行相关策略。

系统变量1:runtime_filter_type。

-- oracle模式
alter system set runtime_filter_type = 'BLOOM_FILTER,RANGE,IN';
-- mysql模式
set runtime_filter_type = 'BLOOM_FILTER,RANGE,IN';

runtime_filter_type的默认值为'BLOOM_FILTER,RANGE,IN',表示启用三种类型的Runtime Filter,当runtime_filter_type='' 时,表示不启用任何类型的Runtime Filter。一般情况下,不需要特别指定runtime_filter_type类型,使用默认值即可,OceanBase会在优化和执行阶段选择最优的Runtime Filter类型进行过滤。

系统变量2:runtime_filter_max_in_num。

默认为1024,代表In Filter使用的默认NDV为1024。若执行时NDV > runtime_filter_max_in_num,则将在执行器自动关闭In filter。一般情况下,不建议用户将该值设置过大,因为在Build表NDV很大的情况下,In Filter的效果不如Bloom Filter。

系统变量3:runtime_filter_wait_time_ms。

Probe端等待Runtime Filter到达的最大等待时间默认10ms,当Runtime Filter到达后,Probe再吐数据。如果超过runtime_filter_wait_time_ms还未到达,则进入by pass阶段,此时不经Runtime Filter过滤直接开始吐数据;当某个时刻Runtime Filter达到后,Runtime Filter仍然会被启用并执行过滤。一般情况下,该值不需要调整,当实际使用Bloom Filter数据很大,且如果知道过滤性比较好的情况下,可以适当调大该值。

系统变量4:runtime_bloom_filter_max_size。

限制Bloom Filter的最大长度默认2048MB。当用户实际使用中build表的数据过多时,默认的Bloom Filter的最大长度将不能容纳数据,会导致Bloom Filter误判率增加,此时需要调大runtime_bloom_filter_max_size以降低其误判率,提高其过滤性。

OceanBasev4.2 Runtime Filter特性

OceanBase自3.1版本以来,支持了Join Bloom Filter用于在Join中执行器扫描数据时快速过滤数据,在4.0版本中,对于Join键为分区列或者分区列前缀场景支持了Partition Bloom FIlter动态过滤分区,之后又在4.1版本支持了多发Bloom Filter使相邻DFO和单个DFO内部均可生成多对Bloom Filter。

在OceanBase的4.2版本中,Join Filter能力再次扩充,在TPCH/TPCDS等场景中进一步获得性能提升,并将其统一称为Runtime Filter(RF)。具体来说,OceanBase的4.2版本新增了以下能力:

  • Global Runtime Filter,支持跨DFO计划中任意位置下压Runtime Filter。区别于之前版本中只能支持相邻DFO和DFO内部传输Runtime Filter,Global Runtime Filter可以在复杂的星形连接中完成横跨CTE及多个DFO下压。
  • 新增In、Range类型的Runtime Filter。在Join左表Join列NDV较小的情况下, 使用In Filter可以精确过滤右侧大表数据,对于数据为数值类型且连续分布通过构建MIN/MAX的Range Filter能够在存储层尤其是列式存储结构中快速过滤数据。

注意事项

以上就是OceanBase中的Runtime Filter能力及其在4.2版本的优化细节。需要注意的是,当Hash Join的过滤性不足时,使用Runtime Filter并不能解决问题,反而可能会导致轻微性能下降。因此,在选择手动开启Runtime Filter的时候,需要对查询场景进行仔细评估,以确定Runtime Filter是否适用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/790040.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[蓝桥杯 2023 省 A]填空问题1

A. 幸运数 小蓝认为如果一个数含有偶数个数位,并且前面一半的数位之和等于后面一半的数位之和,则这个数是他的幸运数字。例如 23142314 是一个幸运数字,因为它有 44 个数位,并且 23142314。现在请你帮他计算从 11 至 10000000010…

若依框架时间比较的坑(DATE_FORMAT)

背景 - 想做生日的比较 若依自带的比较 <if test"params.beginTime ! null and params.beginTime ! "><!-- 开始时间检索 -->AND date_format(u.create_time,%y%m%d) > date_format(#{params.beginTime},%y%m%d)</if><if test"params…

AJAX —— 学习(三)

目录 一、jQuery 中的 AJAX &#xff08;一&#xff09;get 方法 1.语法介绍 2.结果实现 &#xff08;二&#xff09;post 方法 1.语法介绍 2.结果实现 &#xff08;三&#xff09;通用型的 AJAX 方法 1.语法介绍 2.结果实现 二、AJAX 工具库 axios &#xff08;…

java实现小程序授权登录以及获取手机号

1、引入依赖 <dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-miniapp</artifactId><version>4.1.0</version></dependency>2、引入封装好的工具类 import cn.binarywang.wx.miniapp.api.WxMaS…

Opencv各个颜色空间、用途(颜色通道分割与合并)

Opencv各个颜色空间、用途&#xff08;颜色通道分割与合并&#xff09; OpenCV中提供了多种颜色空间&#xff0c;每种颜色空间都有其特定的用途。以下是一些常见的颜色空间及其用途&#xff1a; BGR颜色空间&#xff1a;BGR颜色空间是一种与计算机显示器显示的颜色相同的颜色…

【进阶六】Python实现SDVRPTW常见求解算法——遗传算法(GA)

基于python语言&#xff0c;采用经典遗传算法&#xff08;GA&#xff09;对 带硬时间窗的需求拆分车辆路径规划问题&#xff08;SDVRP&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整2.1 需求拆分2.2 需求拆分后的服务时长取值问题 3. 求解结果4. 代码片段参…

【Qt】Ubuntu20.04.6+Qt5.15.2+QtCreator10.0.1无法输入中文

1、前提条件 1)已经安装了fcitx sudo apt install fcitx sudo apt install fcitx-pinyin sudo apt install fcitx-bin fcitx-table-all sudo apt install fcitx-qt52)系统已经配置fcitx 3)将系统下 /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitx…

计算机考研408有向无环图描述表达式可靠构造方法

目录 前言目标&#xff08;以王道书为例&#xff09;构造方法1. 建树2. 后序遍历1. a2. b3. 4. b5. c6. d7. 8. *9. *10. c 前言 对王道视频中的分层合并思想不是很满意&#xff0c;笔者提出自己的构造方法。 目标&#xff08;以王道书为例&#xff09; 构造方法 笔者通过王…

Doris实践——同程数科实时数仓建设

目录 前言 一、早期架构演进 二、Doris和Clickhouse选型对比 三、新一代统一实时数据仓库 四、基于Doris的一站式数据平台 4.1 一键生成任务脚本提升任务开发效率 4.2 自动调度监控保障任务正常运行 4.3 安全便捷的可视化查询分析 4.4 完备智能的集群监控 五、收益与…

线控悬架系统分析

线控悬架系统分析 附赠自动驾驶学习资料和量产经验&#xff1a;链接 1 线控悬架系统系统发展现状 • 车辆驾乘过程中&#xff0c;操控性和舒适性是两个重要的评价指标&#xff0c;两者很难兼顾&#xff1b; • 线控悬架就是根据路况实际情况自动调节悬架的高度、刚度、阻尼实…

012_control_flow_in_Matlab中的控制流

Matlab中的控制流 虽然&#xff0c;我们说Matlab中的计算是向量化的&#xff0c;但是在某些情况下&#xff0c;作为一个“程序设计语言”&#xff0c;Matlab也提供了一些控制流结构&#xff0c;来帮助我们实现一些复杂的逻辑。 我会在介绍控制流的时候&#xff0c;提醒如何用…

Ansys Zemax | 如何将光栅数据从Lumerical导入至OpticStudio(上)

附件下载 联系工作人员获取附件 本文介绍了一种使用Ansys Zemax OpticStudio和Lumerical RCWA在整个光学系统中精确仿真1D/2D光栅的静态工作流程。将首先简要介绍方法。然后解释有关如何建立系统的详细信息。 本篇内容将分为上下两部分&#xff0c;上部将首先简要介绍方法工…

Python喜马拉雅免费音频数据爬取部署

1. 代码下载 github代码 https://github.com/toilaj/xmly-downloader/tree/main 只能下载免费音频&#xff0c;vip不能下载。 2. 环境部署 下载miniconda3 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh或者链接下载&#xff0c; 寻找linux版…

【Leetcode】top 100 技巧

136 只出现一次的数字 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且该算法只使用常量额外空间。 技巧&#xff1a…

【Redis】解决List类型的消息可靠性问题

前言 平时做后端开发时&#xff0c;如果需要用到消息队列功能&#xff0c;但公司的IT环境又没有提供专业的队列软件&#xff08;RabitMQ/Kafka…&#xff09;&#xff0c;那么在简单场景下&#xff0c;可以使用 Redis 的List数据类型来做消息队列。 但List类型有一个挺致命的…

LeetCode 96. 不同的二叉搜索树

给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5示例 2&#xff1a; 输入&#xff1a;n 1 输出&#xff1a;1提…

34-1 SSRF漏洞 - SSRF服务端请求伪造

一、SSRF漏洞定义: SSRF(Server-side Request Forge)服务器端请求伪造是一种安全漏洞,由于服务端提供了从其他服务器应用获取数据的功能,但没有对地址和协议等进行充分的过滤和限制。攻击者可以利用存在漏洞的Web应用作为代理,从而攻击远程和本地的服务器。由于它是由服务…

有大批量的数据导入到数据库,规则是数据库有相应主键的就update没有就insert怎么做效率快

理此类具有条件的 “upsert”&#xff08;更新或插入&#xff09;操作时&#xff0c;您想要最小化对数据库的访问次数并使用高效的SQL逻辑。以下是几个数据库平台通常使用的方法&#xff1a; MySQL: 在 MySQL 中&#xff0c;可以使用 INSERT ... ON DUPLICATE KEY UPDATE 语句…

代码随想录算法训练营第二十二天| 235.二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

系列文章目录 目录 系列文章目录235. 二叉搜索树的最近公共祖先①递归法自己写的简洁版 ②迭代法不能这样写&#xff01;正确写法 701.二叉搜索树中的插入操作①递归法②迭代法 450.删除二叉搜索树中的节点递归法 235. 二叉搜索树的最近公共祖先 ①递归法 自己写的 class So…

书生·浦语大模型InternLM-Chat-1.8B 智能对话 Demo 第二期

文章目录 InternLM-Chat-1.8B 智能对话 Demo环境准备下载模型运行 InternLM-Chat-1.8B web 运行八戒 demo下载模型执行Demo InternLM-Chat-1.8B 智能对话 Demo 环境准备 在InternStudio平台中选择 10% A100(1/4) 的配置&#xff08;平台资源有限&#xff09;&#xff0c;如下图…