首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL8.0 优化器介绍(三)

MySQL8.0 优化器介绍(三)

作者头像
GreatSQL社区
发布于 2023-08-10 13:52:05
发布于 2023-08-10 13:52:05
45300
代码可运行
举报
运行总次数:0
代码可运行

* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本篇将进一步深入介绍优化器相关的join优化

为更好的理解本篇内容需要提前看一下以下内容:

  1. 单表访问的方法,参考《MySQL 是怎样运行的:从根儿上理解 MySQL》第10章"单表访问方法"
  2. 更多select语句级别的优化细节 见(https://dev.mysql.com/doc/refman/8.0/en/select-optimization.html

为了让读者对join优化 有更深的了解,章节里的sql例子,留了一些思考和动手的问题。可能大家得到的答案会不同,但探索未知的过程,方式应该是一样的。


join优化(Join Optimizations)

MySQL可以使用Join Optimizations来改进上次分享过的join algorithms,或者决定如何执行部分查询。本次主要介绍三种经常用到的join Optimizations,更多的 join type 见下面的链接:(https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#explain-join-types

index merge

通常MySQL只会对每个表使用一个索引。但是,如果对同一表中的多个列在where后有条件限制,并且没有覆盖所有列的单个索引,无论选哪个索引都不是最佳的。对于这些情况,MySQL支持索引合并 (index merge)。select a,b,c from t where a=x1 and b=x2 and c=x3,这种情况下,建立一个多列的复合索引 index_abc 比使用 index merge +index_a+index_b+index_c 性能更好。

Index merge 支持三种算法 见下表

查询计划使用index merge 时,会在explain sql 的 access type 列 有"index_merge",key 列会 包含所有参与merge的列, key_length 包含一个所用索引的最长关键部分的列表。举个Intersection例子:

Intersection

以下代码块注释中提到的知识点略多

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
##无论optimizer 是否选择  index merge 取决于index  statistics. 
## index  statistics 是从哪个试图获得呢?mysql.innodb_index_stats  还是 information_schema.statistics 
## 还是 information_schema.INNODB_SYS_TABLESTATS? 
## 可以参考 https://www.cnblogs.com/ClassicMan/articles/15871403.html
## index_dive  eq_range_index_dive_limit 这两个参数有什么作用?
##意味着即使返回相同STATEMENT_DIGEST_TEXT的sql查询语句, WHERE语句后面跟不同的值,得到的查询计划可能是不一样的  ##比如select * from people where name='唯一值';
##select * from people where name='超级多的重复值'

## 同理index statistics 的改变会让同一个查询走不同的执行计划,
## 体现在 select a,b from t where a=1 and b=1  有时走了 index merges,有时没走。

CREATE TABLE `payment` (
 `payment_id` smallint unsigned NOT NULL,
 `customer_id` smallint unsigned NOT NULL,
 `staff_id` tinyint unsigned NOT NULL,
 `rental_id` int(DEFAULT NULL,
 `amount` decimal(5,2) NOT NULL,
 `payment_date` datetime NOT NULL,
 `last_update` timestamp NULL,
 PRIMARY KEY (`payment_id`),
 KEY `idx_fk_staff_id` (`staff_id`),
 KEY `idx_fk_customer_id` (`customer_id`),
 KEY `fk_payment_rental` (`rental_id`)
) ENGINE=InnoDB;

## case1  等值查询
SELECT *
  FROM sakila.payment
 WHERE staff_id = 1
   AND customer_id = 75;
 
 mysql> EXPLAIN SELECT *
                  FROM sakila.payment
                 WHERE staff_id = 1
                   AND customer_id = 75\G
**************************** 1. row *****************************
 id: 1
 select_type: SIMPLE
 table: payment
 partitions: NULL
 type: index_merge
 possible_keys: idx_fk_staff_id,idx_fk_customer_id
 key: idx_fk_customer_id,idx_fk_staff_id
 key_len: 2,1
 ref: NULL
 rows: 20
 filtered: 100
 Extra: Using intersect(idx_fk_customer_id,idx_fk_staff_id); Using 
where 1 row in set, 1 warning (0.0007 sec)
 
mysql> EXPLAIN FORMAT=TREE
 SELECT *
 FROM sakila.payment
 WHERE staff_id = 1
 AND customer_id = 75\G
**************************** 1. row ****************************
EXPLAIN: -> Filter: ((sakila.payment.customer_id = 75) and (sakila.payment.staff_id = 1)) (cost=14.48 rows=20)
             -> Index range scan on payment using intersect(idx_fk_customer_id,idx_fk_staff_id) (cost=14.48 rows=20)
1 row in set (0.0004 sec)

##注意"Index range scan on payment",两个等值查询条件,为啥触发了rang scan?


## case2  下面的sql范围查询也能用到index  merge 吗?执行计划 自己下去测试验证
SELECT *
 FROM sakila.payment
 WHERE payment_id > 10
 AND customer_id = 318;

Union Algorithm
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
##case1 等值查询
SELECT *
 FROM sakila.payment
 WHERE staff_id = 1
 OR customer_id = 318;
 
 mysql> EXPLAIN
 SELECT *
 FROM sakila.payment
 WHERE staff_id = 1
 OR customer_id = 318\G
**************************** 1. row *****************************
 id: 1
 select_type: SIMPLE
 table: payment
 partitions: NULL
 type: index_merge
 possible_keys: idx_fk_staff_id,idx_fk_customer_id
 key: idx_fk_staff_id,idx_fk_customer_id
 key_len: 1,2
 ref: NULL
 rows: 8069
 filtered: 100
 Extra: Using union(idx_fk_staff_id,idx_fk_customer_id); Using where
1 row in set, 1 warning (0.0008 sec)
 
 mysql> EXPLAIN FORMAT=TREE
 SELECT *
 FROM sakila.payment
 WHERE staff_id = 1
 OR customer_id = 318\G
**************************** 1. row ****************************
EXPLAIN: -> Filter: ((sakila.payment.staff_id = 1) or (sakila.payment.customer_id = 318)) (cost=2236.18 rows=8069)
             -> Index range scan on payment using union(idx_fk_staff_id,idx_fk_customer_id) (cost=2236.18 rows=8069)
1 row in set (0.0010 sec)

 ## case2 范围查询也能用到index  merge 吗?执行计划 自己下去测试验证, 
 ## 有主键参与后,和Intersection 章节的case2 执行计划中用到的索引个数有啥不同?
SELECT *
 FROM sakila.payment
 WHERE payment_id > 15000
 OR customer_id = 318;
Sort-Union Algorithm
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT *
 FROM sakila.payment
 WHERE customer_id < 30
 OR rental_id < 10;
 
 mysql> EXPLAIN
 SELECT *
 FROM sakila.payment
 WHERE customer_id < 30
 OR rental_id < 10\G
**************************** 1. row *****************************
 id: 1
 select_type: SIMPLE
 table: payment
 partitions: NULL
 type: index_merge
possible_keys: idx_fk_customer_id,fk_payment_rental
 key: idx_fk_customer_id,fk_payment_rental
 key_len: 2,5
 ref: NULL
 rows: 826
 filtered: 100
 Extra: Using sort_union(idx_fk_customer_id,fk_payment_rental); 
Using where 1 row in set, 1 warning (0.0009 sec)

mysql> EXPLAIN FORMAT=TREE
 SELECT *
 FROM sakila.payment
 WHERE customer_id < 30
 OR rental_id < 10\G
**************************** 1. row *****************************
EXPLAIN: -> Filter: ((sakila.payment.customer_id < 30) or (sakila.payment.rental_id < 10)) (cost=1040.52 rows=826)
             -> Index range scan on payment using sort_union(idx_fk_customer_id,fk_payment_rental) (cost=1040.52 rows=826)
1 row in set (0.0005 sec)

Multi-Range Read (MRR)

多范围读取(MRR)优化旨在减少对辅助索引进行范围扫描所导致的随机I/O量。优化读取索引

首先,根据行id(InnoDB的聚集索引)对键进行排序,然后按行的存储顺序检索行。多量程读取优化

可以用于范围扫描和使用索引的等值连接。不支持虚拟生成列上的辅助索引。

使用InnoDB进行多范围读取优化的主要用例是用于没有覆盖索引的磁盘绑定查询( disk-bound queries 另外一个层面对disk-bound 的优化,详细可见:https://dev.mysql.com/doc/refman/8.0/en/optimizing-innodb-diskio.html)。优化的效果取决于需要多少行以及存储器的查找时间。MySQL将会估算(estimate)是否有用。然而,成本估算在过于悲观而不是过于乐观的一面,因此可能有必要提供帮助优化器做出正确决策的信息。

有两个 optimizer switches 控制MRR优化

  • mrr: Whether the optimizer is allowed to use the Multi-Range Read optimization. The default is ON.
  • mrr_cost_based: Whether the decision to use the Multi-Range Read optimization is cost based. You can disable this option to always use the optimization when it is supported. The default is ON

可以用MRR() 和NO_MRR() 两个optimizer switches 来控制表级别or 索引级别的 Multi-Range Read ,举个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mysql> EXPLAIN
 SELECT /*+ MRR(city) */
 *
 FROM world.city
 WHERE CountryCode BETWEEN 'AUS' AND 'CHN'\G
**************************** 1. row *****************************
 id: 1
 select_type: SIMPLE
 table: city
 partitions: NULL
 type: range
possible_keys: CountryCode
 key: CountryCode
 key_len: 3
 ref: NULL
 rows: 812
 filtered: 100
 Extra: Using index condition; Using MRR
1 row in set, 1 warning (0.0006 sec)


有必要使用MRR()优化器提示或禁用基于MRR_cost_based的优化器开关。
示例中查询的估计行数太小,没有MRR的hint时,基于成本的优化无法使用MRR。
只能显示用hint来干预查询计划使用MRR。
当MRR的优化被使用时, MySQL需要用到random read buffer来存储indexes. 
有一个参数可以影响MRR的性能 read_rnd_buffer_size.

Batched Key Access (BKA)

可以简单认为 BKA=BNL+MRR .这使得可以以与非索引连接类似的方式将连接缓冲区用于索引连接,并使用多范围读取优化来减少随机I/O的数量。BKA 用于大量 disk-bound 查询的场景。但是,没有明确的说明来确定优化何时有帮助,何时会导致性能下降。

可以借鉴一下国外知名dba在MySQL 优化方面的blog(http://oysteing.blogspot.com/2012/04/improved-dbt-3-results-with-mysql-565.html

MRR 在最优时,查询耗时减少20%,最糟糕时查询耗时增加2/3。

BKA 主要的获益在一个相对较窄的查询范围,而其他查询的性能可能会降低,因此默认情况下禁用该优化。

(可以简单理解为 MySQL5.6时,bka优化带来的收益小于bka带来的成本开销)除非确定开启bka能来提升时,再用hint BKA() 来启用。session级别开启:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SET SESSION optimizer_switch = 'mrr=on,mrr_cost_based=off,batched_key_access=on';

一个使用BKA的例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mysql> EXPLAIN
 SELECT /*+ BKA(ci) */
 co.Code, co.Name AS Country,
 ci.Name AS City
 FROM world.country co
 INNER JOIN world.city ci
 ON ci.CountryCode = co.Code\G
**************************** 1. row *****************************
 id: 1
 select_type: SIMPLE
 table: co
 partitions: NULL
 type: ALL
 possible_keys: PRIMARY
 key: NULL
 key_len: NULL
 ref: NULL
 rows: 239
 filtered: 100
 Extra: NULL
**************************** 2. row *****************************
 id: 1
 select_type: SIMPLE
 table: ci
 partitions: NULL
 type: ref
 possible_keys: CountryCode
 key: CountryCode
 key_len: 3
 ref: world.co.Code
 rows: 18
 filtered: 100
 Extra: Using join buffer (Batched Key Access)
2 rows in set, 1 warning (0.0007 sec)

注意看执行计划中Extra 的关键字 "Using join buffer",说明 join_buffer_size 会影响BKA 特性的性能。从全局怎么调整join_buffer_size,并又能充分利用上BKA,是一个极大的挑战。调优最常见的问题,搞定了A sql,又引出了其他问题,比如内存使用率过高。

其他join优化

MySQL 还自动支持其他join 优化,一旦对查询有性能帮助,优化器会自动选择他们,一般不需要手动。

了解一下其他join的优化方式,有助于我们在遇到sql性能问题时,可以适当给与优化器,一些有用的hint。

具体有哪些join 优化方式,可以查看explain 输出中的Extra 的内容说明。本文可能列举的不全,精力有限只做了一些简单的介绍,具体细节需要查看官网,以及大量的实践。

  1. Condition Filtering 条件过滤 当一个表有两个或多个与之相关联的条件,并且一个索引可以用于部分条件时,使用条件过滤优化。启用条件过滤后,在估计表的总体过滤时,将考虑其余条件的过滤效果。
    • Optimizer Switch: condition_fanout_filter – enabled by default
    • Optimizer Hints: None
    • EXPLAIN Output: None
  2. Derived Merge 优化器可以将派生表(derived table)、视图引用和公共表表达式合并到它们所属的查询块中。优化的替代方法是物化表(materialize the table)、视图引用或公共表表达式。
    • Optimizer Switch: derived_merge – enabled by default.
    • Optimizer Hints: MERGE(), NO_MERGE().
    • EXPLAIN Output: The query plan reflects that the derived table has been merged
  3. Engine Condition Pushdown 此优化将条件向下推到存储引擎。目前仅NDBCluster存储引擎支持它。
  4. Index Condition Pushdown 官方文档中给的例子和解释如下:people表中(zipcode,lastname,firstname)构成一个索引 SELECT * FROM people WHERE zipcode='95054' AND lastname LIKE '%etrunia%' AND address LIKE '%Main Street%'; 如果没有使用索引下推技术,则MySQL会通过zipcode='95054'从存储引擎中查询对应的数据,返回到MySQL服务端,然后MySQL服务端基于lastname LIKE '%etrunia%'和address LIKE '%Main Street%'来判断数据是否符合条件。 如果使用了索引下推技术,则MySQL首先会返回符合zipcode='95054'的索引,然后根据lastname LIKE '%etrunia%'和address LIKE '%Main Street%'来判断索引是否符合条件。如果符合条件,则根据该索引来定位对应的数据,如果不符合,则直接reject掉。 有了索引下推优化,可以在有like条件查询的情况下,减少回表次数。 该优化也用于二级索引的范围条件。
    • Optimizer Switch: index_condition_pushdown – enabled by default.
    • Optimizer Hints: NO_ICP().
    • EXPLAIN Output: The traditional format has Using index condition in the Extra column, and the JSON format sets the index_condition field with the index condition that is pushed
  5. Index Extensions InnoDB中的所有二级非唯一索引都将主键列附加到索引中。当启用索引扩展优化时,MySQL会将主键列视为索引的一部分。
    • Optimizer Switch: use_index_extensions – enabled by default
    • Optimizer Hints: None
    • EXPLAIN Output: None
  6. Index Visibility 当表具有不可见的索引( invisible index)时,默认情况下,优化器在创建查询计划时不会考虑它。如果启用了索引可见性优化器开关,则将考虑不可见的索引。例如,这可以用于测试已添加但尚未可见的索引的效果。
    • Optimizer Switch: use_invisible_indexes – disabled by default
    • Optimizer Hints: None
    • EXPLAIN Output: None
  7. Loose Index Scan 在某些情况下,MySQL可以使用部分索引来提高聚合数据或包含DISTINCT子句的查询的性能。这要求列用于通过形成多列索引的左前缀以及不用于分组的其他列来分组数据。当存在GROUP BY子句时,只有MIN()和MAX()聚合函数才能使用这个特性。 distinct效率更高还是group by效率更高?
    • Optimizer Switch: None.
    • Optimizer Hints: NO_RANGE_OPTIMIZATION() disables the loose index scan optimization as well as index merges and range scans.
    • EXPLAIN Output: The traditional format has Using index for group-by in the Extra column. The JSON format sets the using_index_for_group_by field to true.
  8. Range Access Method 范围优化与其他优化略有不同,因为它被认为是一种访问方法。MySQL将只扫描表或索引的一个或多个部分,而不是执行完整的表或索引扫描。范围访问方法通常用于涉及运算符>、>=、<、=<、BETWEEN、IN(),为NULL、LIKE等 range-Optimization 与 index merge Optimization 具有同样的重要性。(https://dev.mysql.com/doc/refman/8.0/en/range-optimization.html
    • Optimizer Switch: None.
    • Optimizer Hints: NO_RANGE_OPTIMIZATION() – this also disables the loose index scan and index merge optimizations. It does however not disable the skip scan optimization even though that also uses range access.
    • EXPLAIN Output: The access method is set to range. range_optimizer_max_mem_size 可以限制 range access使用的内存。默认是8M
  9. Semijoin 半联接优化用于IN和EXIST条件。支持四个策略: 当subquery materialization 开启时, Semijoin 会尽可能的使用 materialization策略。EXISTS 在MySQL8.0.16 以后支持半联接。NOT EXISTS 在MySQL8.0.17 以后支持半联接。每种策略,都可以 以参数的形式,用于SEMIJOIN() and NO_SEMIJOIN() hint SEMIJOIN(DUPSWEEDOUT):The duplicate weedout strategy executes the semijoin as if it is a normal join and removes the duplicates using a temporary table. EXPLAIN Output: The traditional format has Start temporary and End temporary in the Extra column for the tables involved. The JSON-formatted output uses a block named duplicates_removal SEMIJOIN(FIRSTMATCH):The first match strategy returns the first match for each value rather than all values. EXPLAIN Output: The traditional format has FirstMatch(...) in the Extra column where the value between parentheses is the name of the reference table. The JSON format sets the value of the first_match field to the name of the reference table SEMIJOIN(LOOSESCAN):The loose scan strategy uses an index to choose a single value from each of the subquery’s value groups. EXPLAIN Output: The traditional format has LooseScan(m..n) in the Extra column where m and n indicate which parts of the index are used for the loose scan. The JSON format sets the loosescan field equal to true 半连接特别怕 null 值,Oracle 经常在以下方面出问题:
    • where null in (a,b,c,null), null exists (null) .
    • sum(null) 返回null,count(null) 返回 0
    • materialization
    • duplicate weedout
    • first match
    • loose scan (不要和 loose index scan optimization混淆)。
  10. Skip Scan Skip Scan MySQL 8.0.13 引入,工作方式类似loose index scan.当多列索引的第二列上存在范围条件,但第一列上没有条件时使用。Skip Scan将整个索引扫描转换为一系列范围扫描(对索引中第一列的每个值进行一次范围扫描)。 scan in the Extra column, and the JSON format sets the using_index_for_skip_scan field to true
    • Optimizer Switch: skip_scan – enabled by default.
    • Optimizer Hints: SKIP_SCAN(), NO_SKIP_SCAN().
    • EXPLAIN Output: The traditional format has Using index for skip
  11. Subquery Materialization 子查询物化策略将子查询的结果存储在内部临时表中。如果可能的话,优化器将在临时表上添加一个自动生成的哈希索引,将使其快速连接到查询的其余部分。 当启用了subquery_materialization_cost_based优化器开关(默认开)时,优化器将使用估计的成本来决定是使用Subquery Materialization 还是使用 IN-to-EXIST子查询转换(将IN条件重写为EXISTS)。 当开关关闭时,优化器总是选择Subquery Materialization。
    • Optimizer Switch: materialization – enabled by default.
    • Optimizer Hints: SUBQUERY(MATERIALIZATION).
    • EXPLAIN Output: The traditional format has MATERIALIZED as the select type. The JSON format creates a block named materialized_from_subquery.

还有我们可以用哪些方法影响优化器,下篇文章再续。

Enjoy GreatSQL :)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GreatSQL社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
还有kylinshell这个终端工具也挺好用的,功能比较简单。
还有kylinshell这个终端工具也挺好用的,功能比较简单。
回复回复点赞举报
推荐阅读
Java基础(八):封装、继承、多态与关键字this、super详解
Java基础(五):流程控制全解析——分支(if/switch)和循环(for/while)的深度指南
Java微观世界
2025/07/17
900
LLM入门2 | 羊驼AIpaca | Stanford
斯坦福的研究,从LLaMA 7B模型在52k的instruction-following demonstrations上微调得到的模型,AIpaca 7B. 主打就是一个低成本,小于600刀。据说和text-davinci-003具有相类似的性能,也就是我们所说的GPT-3.5。
机器学习炼丹术
2023/09/02
6630
LLM入门2 | 羊驼AIpaca | Stanford
CausalDiscoveryToolbox:因果建模、因果图代码实现
最近在分析观测数据的因果关系时,发现一个很好用的工具包——CausalDiscoveryToolbox(以下简称Cdt),功能齐全,轻松上手因果发现。 下面简单整理下该工具包的原理+用法。
全栈程序员站长
2022/09/21
1.6K0
CausalDiscoveryToolbox:因果建模、因果图代码实现
Postgresql源码(60)事务系统框架总结
用户命令触发状态机函数导致事务状态流转,流转时按对应状态调用底层事务处理函数干活。
mingjie
2022/07/14
7150
【ChatGPT】一个凭借两百多年历史的公式崛起的巨星
托马斯·贝叶斯 (Thomas Baves,1701年一1761年),是18世纪的一位英国数学家、统计学家
THUNDER王
2023/10/13
3890
【ChatGPT】一个凭借两百多年历史的公式崛起的巨星
使用flask框架实现简单的图书管理(python 3.8)
flask是轻量级的web框架。 浏览器作为client发出HTTP请求,而web服务器负责处理逻辑,而flask帮助我们完成了安全性和数据流的控制,让我们只用关注于业务逻辑本身,避免重复造轮子
用户7886150
2020/12/30
7780
Mybatis分页插件使用的详解[通俗易懂]
关于分页,一般来说rowBounds 这种假分页都上不了台面,我们往往都选哟真分页,那么还不想搞得很麻烦,Mybatis的分页插件就为后端程序员解决了这个问题
全栈程序员站长
2022/11/07
7140
Spring全家桶 源码 入门系列(二) --------AOP深度剖析
com.libin.a13.ProxyFastClass,com.libin.a13.TargetFastClass
猫头虎
2024/04/08
1330
ES中文检索须知:分词器与中文分词器
分词即为将doc通过Analyzer切分成一个一个Term(关键字),es分词在索引构建和数据检索时均有体现:
Steve Wang
2024/04/22
1.1K0
ES中文检索须知:分词器与中文分词器
如何使用potplayer在公网环境访问内网群晖NAS中储存在webdav中的影视资源
#mermaid-svg-D7WJh3JaNVrLcj2b {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-D7WJh3JaNVrLcj2b .error-icon{fill:#552222;}#mermaid-svg-D7WJh3JaNVrLcj2b .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-D7WJh3JaNVrLcj2b .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-D7WJh3JaNVrLcj2b .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-D7WJh3JaNVrLcj2b .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-D7WJh3JaNVrLcj2b .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-D7WJh3JaNVrLcj2b .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-D7WJh3JaNVrLcj2b .marker{fill:#333333;stroke:#333333;}#mermaid-svg-D7WJh3JaNVrLcj2b .marker.cross{stroke:#333333;}#mermaid-svg-D7WJh3JaNVrLcj2b svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-D7WJh3JaNVrLcj2b .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-D7WJh3JaNVrLcj2b .cluster-label text{fill:#333;}#mermaid-svg-D7WJh3JaNVrLcj2b .cluster-label span{color:#333;}#mermaid-svg-D7WJh3JaNVrLcj2b .label text,#mermaid-svg-D7WJh3JaNVrLcj2b span{fill:#333;color:#333;}#mermaid-svg-D7WJh3JaNVrLcj2b .node rect,#mermaid-svg-D7WJh3JaNVrLcj2b .node circle,#mermaid-svg-D7WJh3JaNVrLcj2b .node ellipse,#mermaid-svg-D7WJh3JaNVrLcj2b .node polygon,#mermaid-svg-D7WJh3JaNVrLcj2b .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-D7WJh3JaNVrLcj2b .node .label{text-align:center;}#mermaid-svg-D7WJh3JaNVrLcj2b .node.clickable{cursor:pointer;}#mermaid-svg-D7WJh3JaNVrLcj2b .arrowheadPath{fill:#333333;}#mermaid-svg-D7WJh3JaNVrLcj2b .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-D7WJh3JaNVrLcj2b .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-D7WJh3JaNVrLcj2b .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-D7WJh3JaNVrLcj2b .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-D7WJh3JaNVrLcj2b .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-D7WJh3JaNVrLcj2b .clust
ImAileen
2024/04/02
3580
如何使用potplayer在公网环境访问内网群晖NAS中储存在webdav中的影视资源
Flowith:打造智能工作流的技术利器,别再求Manus邀请码了!
在AI智能体技术快速发展的2024年,工作流引擎正在经历从静态脚本到动态认知的范式转变。Flowith作为新一代智能体协作平台,通过其创新的分布式架构和模块化设计,在复杂任务处理领域展现出独特的技术优势。本文将从系统架构、核心特性到实践案例,深入解析这一前沿工具的技术实现。
鲲志说
2025/04/07
7010
Flowith:打造智能工作流的技术利器,别再求Manus邀请码了!
Postgresql源码(56)可扩展类型分析ExpandedObject/ExpandedRecord
ExpandedObjectHeader总结:在应用时注意第七点,有的函数(datumCopy)需要的不是EOH头(4B头),是需要一个eoh_rw_ptr指针(1b_e头)。在使用函数前确认好datum传什么进去。
mingjie
2022/06/30
5330
Postgresql源码(56)可扩展类型分析ExpandedObject/ExpandedRecord
赶走烦人的“if-else”,使用状态模式推动业务生命周期的流转
本文借助海外互金业务的借款流程展开。业务核心是借款的生命周期,相当于是电商中的订单一样。一笔借款的整个生命周期包含了提交,审批,确认,放款,还款。一笔借款的状态对应已上的操作,同样就很多了。如图是一笔借款的生命周期:
闻说社
2023/03/20
3990
【初探数据结构】带环链表:原理、判断与数学证明
由节点构成的链式结构中存在至少一个节点,其指针域指向链表中已存在的节点,形成闭合环路。特征:
我想吃余
2025/03/31
1160
【初探数据结构】带环链表:原理、判断与数学证明
梳理一下各大平台使用的sample rate convert算法
转采样属于数字信号重建的范畴,整数倍的升降采样可以通过插值抽取+带限滤波的方法【1】,并且通过级联来实现任意比值的采样率转换。这里需要对奈奎斯特采样定理,以及数字信号时频关系有比较清晰的理解。还有一种方法是插值,插值的方法比较多,在参考里有一阶保持FOH、零阶保持ZOH、三次样条函数spline和sinc函数,引用的博文中有比较直观的分析和事例。那么在各大平台,最后都是用什么实现的resample重建呢?
全栈程序员站长
2022/11/03
1.2K0
梳理一下各大平台使用的sample rate convert算法
大模型基础知识 - 语言模型及其演进 公开版
自然语言处理在大语言模型(Large Language Model, LLM)被提出之后,再次取得重大突破:
Steve Wang
2023/10/12
5620
大模型基础知识 - 语言模型及其演进 公开版
Spring全家桶 源码 入门系列(一) --------容器与 bean
可以看到,我们课上讲的,都是 BeanFactory 提供的基本功能,ApplicationContext 中的扩展功能都没有用到。
猫头虎
2024/04/08
1730
【MySQL】学习如何通过DML更新数据库的数据
#mermaid-svg-QIqURn9fNFMjLD9l {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QIqURn9fNFMjLD9l .error-icon{fill:#552222;}#mermaid-svg-QIqURn9fNFMjLD9l .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QIqURn9fNFMjLD9l .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-QIqURn9fNFMjLD9l .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QIqURn9fNFMjLD9l .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QIqURn9fNFMjLD9l .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QIqURn9fNFMjLD9l .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QIqURn9fNFMjLD9l .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QIqURn9fNFMjLD9l .marker.cross{stroke:#333333;}#mermaid-svg-QIqURn9fNFMjLD9l svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QIqURn9fNFMjLD9l .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QIqURn9fNFMjLD9l .cluster-label text{fill:#333;}#mermaid-svg-QIqURn9fNFMjLD9l .cluster-label span{color:#333;}#mermaid-svg-QIqURn9fNFMjLD9l .label text,#mermaid-svg-QIqURn9fNFMjLD9l span{fill:#333;color:#333;}#mermaid-svg-QIqURn9fNFMjLD9l .node rect,#mermaid-svg-QIqURn9fNFMjLD9l .node circle,#mermaid-svg-QIqURn9fNFMjLD9l .node ellipse,#mermaid-svg-QIqURn9fNFMjLD9l .node polygon,#mermaid-svg-QIqURn9fNFMjLD9l .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QIqURn9fNFMjLD9l .node .label{text-align:center;}#mermaid-svg-QIqURn9fNFMjLD9l .node.clickable{cursor:pointer;}#mermaid-svg-QIqURn9fNFMjLD9l .arrowheadPath{fill:#333333;}#mermaid-svg-QIqURn9fNFMjLD9l .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QIqURn9fNFMjLD9l .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QIqURn9fNFMjLD9l .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-QIqURn9fNFMjLD9l .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-QIqURn9fNFMjLD9l .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QIqURn9fNFMjLD9l .clust
ImAileen
2024/01/28
4800
【MySQL】学习如何通过DML更新数据库的数据
TensorFlow 深度学习框架详解
TensorFlow 是由 Google Brain 团队开发的开源机器学习框架,其名称源于处理多维数据数组(张量)的数据流图(Flow)的运行方式。
奶油话梅糖
2025/03/26
5450
77.HarmonyOS NEXT ImageViewerView 组件深度剖析: Swiper容器与懒加载深度解析
全栈若城
2025/03/16
860
推荐阅读
相关推荐
Java基础(八):封装、继承、多态与关键字this、super详解
更多 >
LV.4
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档