ClickHouse 26.8 版本发布说明:长期支持版本带来 98 项新功能与多项性能优化

三极管共集电极放大电路详解:射极跟随器的原理、计算与应用 三极管放大电路是模拟电子技术的基石,常见组态包括共发射极、共基极和共集电极。其中共集电极电路因输入电阻大、输出电阻小、电压增益接近1的特性,常被用作射极跟随器,在信号缓冲、级间隔离和低阻抗负载驱动等场景中发挥关键作用。其核心价值并非电压放大,而是完成阻抗变换,将高内阻信号源转换为低内阻输出,同时保持信号幅值基本不变。理解其静态工作点计算与动态参数推导(如电压增益、输入输出电阻)是设计实用电路的前提。本文结合12V电源下的具体设计实例和仿真验证,梳理了从电路识别、参数计算到工程实践的完整流程,并指出常见设计误 阅读详情

图片

本文字数:23451;估计阅读时间:59分钟

作者:ClickHouse

图片

编者按: 本文译自 ClickHouse 原博客。 原文围绕「ClickHouse 26.8 以长期支持版本形式交付功能扩展与性能提升。」展开。本次更新在功能与性能两条线上均有实质推进,长期支持定位也降低了生产环境的升级顾虑。数据湖集成与 join 性能的改进值得关注。

又过了一个月,又到了发布新版本的时候!

ClickHouse 26.8 版本包含 98 项新功能 🍇、128 项性能优化 🌠、556 个 bug 修复 🐝,并且是长期支持版本。

本次发布带来后台查询、流水线 SQL、新的文本分词器、扩展的数据湖集成,以及 Parquet、GROUP BY 和 join 的性能改进。

新贡献者

特别欢迎 26.8 的所有新贡献者!ClickHouse 社区的增长令人惊叹,我们始终感谢那些让 ClickHouse 如此受欢迎的贡献。

以下为新贡献者名单:

Aashish Kohli, AbdullahKaya, Alex Budkar, Alex Kalmakov, Alexey Elkin, Amog Iska, Amogh-Bharadwaj, Andrey Tsarevskiy, Andy Bradshaw, Avinash Kamath, Bartok, Bartok9, Chris Lu, Christian Bianchi, ClickGap, Daniel Q. Kim, David Dallakyan, Dean Chen, Dergousov Maksim, Diego Gomes Tomé, Dmitrii Tunikov, Eduardo Gómez, Emil Sadek, George MacRorie, Hamid, Hank Cui, Haowen Feng (from Dev Box), Ilia Demianenko, Ivan Shelestov, James Sanders, Jose Muñoz, KD2YCU, Kirill Shcherbatov, Kirill Shokhin, Konstantin Plis, Kseniia, Nikolai Ovchinnikov, Nishant, Nishant Agarwal, Nuno Adrego, Perfloop Agent, Rahul Malik, RamiDarwiche, Raymond Lee, Ria Khatoniar, Ria-K912, Rohith Pariki, RohithPariki, Schum, Sean Reid, Sergey Chernov, Shawn Chen, Stanislav, Steve Lerner, Tod Trevillian, UberDever, Utkal Singh, Valery Petrov, VighneshPath, Vladimir Chemeris, William Hatcher, Yecine Megdiche, Yiyang Shao, ZachEddy, Zeynel Koca, a.akhondi, addshore, amirreza1307, avinash, deusgaudio, francisconeves-clickhouse, gelsonbagetti, gudauu, kalyanamdewri, locadex-agent[bot], pavol kutaj, quantrail-admin, vahid, vahid sohrabloo, yisamlee, yiyang-shao, zainulabidin302, Éco

提示:如果你好奇我们如何生成这份名单……看这里(https://gist.github.com/gingerwizard/5a9a87a39ba93b422d8640d811e269e9)。

查看媒体链接:https://www.youtube.com/watch?v=5A9gRYE0v2M

你还可以查看演示文稿的幻灯片(https://presentations.clickhouse.com/2026-release-26.8/)。

在后台运行查询

由 Miсhael Stetsyuk 贡献

现在可以在后台运行查询。查询会立即返回,然后持续运行直到完成,无论连接发生什么。

这个功能适合向 ClickHouse 写入数据或从中导出数据的长时间查询,即使客户端断开连接,这些查询也能继续运行。

我们有一台 ClickHouse 服务器正在运行,已导入 UK property prices dataset,然后用下面的查询复制了几次:

ALTER TABLE uk_price_paid
ATTACH PARTITION ID 'all'
FROM uk_price_paid;

这样行数就略超过 2.4 亿:

SELECT count() FROM uk_price_paid;
┌───count()─┐
│ 243619704 │
└───────────┘

接下来,我们可以运行下面的查询,把 uk_price_paid 表中的数据写入本地 HTTP 服务器上的一个文件。

INSERT INTO FUNCTION url('http://localhost:8080/uploads/london-sales.parquet', 'Parquet')
SELECT * FROM uk_price_paid
SETTINGS run_query_in_background = 1;
Query id: 59eabb9f-33f4-412b-b2f3-b090fe7b4bbf

Ok.

0 rows in set. Elapsed: 0.001 sec.

我们可以查询 system.processes,查看后台查询的进度:

SELECT query_id, query,
      round(elapsed, 2) AS elapsed_seconds,
      read_rows, written_rows
FROM system.processes
WHERE query NOT ILIKE '%system.processes%'
ORDER BY elapsed DESC;
Row 1:
──────
query_id:        59eabb9f-33f4-412b-b2f3-b090fe7b4bbf
query:           INSERT INTO FUNCTION url('http://localhost:8080/uploads/uk.parquet', 'Parquet')
SELECT * FROM uk_price_paid
SETTINGS run_query_in_background = 1;
elapsed_seconds: 8.52
read_rows:       179243204 -- 179.24 million
written_rows:    179243204 -- 179.24 million

查询完成后,可以查询 system.query_log,看看它花了多长时间:

SELECT event_time, type, query_duration_ms,
      read_rows, result_rows
FROM system.query_log
WHERE query_id = '59eabb9f-33f4-412b-b2f3-b090fe7b4bbf'
ORDER BY event_time;
┌──────────event_time─┬─type────────┬─query_duration_ms─┬─read_rows─┬─result_rows─┐
│ 2026-09-03 12:32:05 │ QueryStart  │                 0 │         0 │           0 │
│ 2026-09-03 12:32:17 │ QueryFinish │             11798 │ 243619704 │   243619704 │
└─────────────────────┴─────────────┴───────────────────┴───────────┴─────────────┘

PostgreSQL 风格的正则表达式运算符

由 Alexey Milovidov 贡献

ClickHouse 现在支持以下 PostgreSQL 风格的正则表达式运算符:

• ~ 在字符串匹配正则表达式时返回 1,区分大小写。

• ~* 在字符串匹配正则表达式时返回 1,不区分大小写。

• !~ 在字符串不匹配正则表达式时返回 1,区分大小写。

• !~* 在字符串不匹配正则表达式时返回 1,不区分大小写。

下面的查询演示如何用所有这些运算符匹配 Baker Street 的各个部分:

SELECT
      'Baker Street' ~ 'street$' AS matchesCaseSensitively,
      'Baker Street' ~* 'street$' AS matchesCaseInsensitively,
      'Baker Street' !~ 'street$' AS doesNotMatchCaseSensitively,
      'Baker Street' !~* 'street$' AS doesNotMatchCaseInsensitively
FORMAT Vertical;
Row 1:
──────
matchesCaseSensitively:        0
matchesCaseInsensitively:      1
doesNotMatchCaseSensitively:   1
doesNotMatchCaseInsensitively: 0

一点免责声明: 这些运算符的实现者 Alexey 附带了一句提醒:他本人并不喜欢它们,觉得它们会让 SQL 看起来太像 Bash 或 Perl。这一轮,PostgreSQL 兼容性胜出。同一项改动还意味着,通过 PostgreSQL 线协议连接 ClickHouse 时,\d、\dt、\dv 等 psql 命令现在可以用了。不过,\d <table> 仍依赖一些 ClickHouse 尚未支持的 PostgreSQL 语法。

数组作为数组下标

由 folly 贡献

下标运算符现在可以接受一组索引,并返回所有指定位置上的元素。这样一来,就能在单个表达式里收集、重排或抽样数组元素;与 arraySort 和 topK 类函数一起用时很方便。

来看一个简单的例子:

WITH arrayMap(x -> rand(x), range(1, 10)) AS random_values
SELECT random_values[[1, 3, 5]];
┌─arrayElement(ran⋯ues, [1, 3, 5])─┐
│ [344408953,1157293782,407846805] │
└──────────────────────────────────┘

更实际的用法是从月度时间序列中选取季度检查点。下面的查询先为每个区域的月度中位价格构建有序数组,然后用一个表达式选出 1 月、4 月、7 月和 10 月:

WITH monthlyPrices AS
(
    SELECT district, toStartOfMonth(date) AS month,
           round(median(price)) AS medianPrice
    FROM uk_price_paid
    WHERE town = 'LONDON'
      AND district IN ('CAMDEN', 'CITY OF WESTMINSTER', 'KENSINGTON AND CHELSEA')
      AND date >= '2024-01-01' AND date < '2025-01-01'
    GROUP BY district, month
)
SELECT district,
       arraySort(groupArray((month, medianPrice)))[[1, 4, 7, 10]] AS quarterlyPrices
FROM monthlyPrices
GROUP BY district
HAVING count() = 12
ORDER BY district;
Row 1:
──────
district:        CAMDEN
quarterlyPrices: [('2024-01-01',760000),('2024-04-01',731000),('2024-07-01',762500),('2024-10-01',805000)]

Row 2:
──────
district:        CITY OF WESTMINSTER
quarterlyPrices: [('2024-01-01',1215000),('2024-04-01',1037500),('2024-07-01',935000),('2024-10-01',875000)]

Row 3:
──────
district:        KENSINGTON AND CHELSEA
quarterlyPrices: [('2024-01-01',1205000),('2024-04-01',1187500),('2024-07-01',1100000),('2024-10-01',1200000)]

查询转 JSON 再转查询

贡献者:Alexey Milovidov、Nikita Fomichev

现在,既可以把查询转换成 JSON 格式的抽象语法树,也可以用 JSON 格式的抽象语法树来查询 ClickHouse。

parseQueryToJSON 函数返回 JSON 格式的抽象语法树。我们用一个简单的 count() 来演示这个函数,因为输出非常冗长:

SELECT parseQueryToJSON($sql$
SELECT count() FROM uk_price_paid
$sql$)::JSON
FORMAT Vertical;
{
  "type": "SelectWithUnionQuery",
  "union_mode": "UNION_DEFAULT",
  "list_of_selects": {
    "type": "ExpressionList",
    "children": [
      {
        "type": "SelectQuery",
        "select": {
          "type": "ExpressionList",
          "children": [
            {"type": "Function", "name": "count",
             "arguments": {"type": "ExpressionList"}}
          ]
        },
        "tables": {
          "type": "TablesInSelectQuery",
          "children": [
            {"type": "TablesInSelectQueryElement",
             "table_expression": {
               "type": "TableExpression",
               "database_and_table_name": {
                 "type": "TableIdentifier", "name": "uk_price_paid"}}}
          ]
        }
      }
    ]
  }
}

JSON 把查询描述为一棵带类型的节点树:标识符、字面量、函数和子句。

由于它就是普通的 JSON,任何有 JSON 库的语言都能分析、验证、重写或生成查询,无需嵌入 SQL 解析器。

转换是双向的:formatQueryFromJSON 能把树转回 SQL,所以你随时可以读回自己构建的内容:

SELECT formatQueryFromJSON(parseQueryToJSON($sql$
SELECT count() FROM uk_price_paid
$sql$));
┌─formatQueryFromJ⋯_price_paid\n'))─┐
│ SELECT count() FROM uk_price_paid │
└───────────────────────────────────┘

ClickHouse 26.8 还新增了一个实验性方言 clickhouse_json,允许你发送 JSON AST 而不是 SQL。它由 enable_json_ast_dialect 设置控制,然后像其他方言一样选择:

SET enable_json_ast_dialect = 1, dialect = 'clickhouse_json';

如果我们粘贴之前创建的 SELECT count() FROM uk_price_paid 的 AST,会得到:

┌───count()─┐
│ 243619704 │
└───────────┘

我们并不指望你开始用 JSON 语法树写查询!这个功能更多是给机器用的,而不是给人用的。

任何生成查询的东西都可以生成 JSON 语法树,而不是 SQL。这意味着不再需要拼接字符串,不再有可怕的转义 bug,也许最重要的是,没有 SQL 注入面。

CREATE USER... VALID FOR

贡献者:Alexey Milovidov

在 ClickHouse 26.8 之前,已经可以用 VALID UNTIL 语法创建有时间限制的用户:

CREATE USER mark
IDENTIFIED WITH no_password
VALID UNTIL '2026-10-04';

ClickHouse 26.8 新增了 VALID FOR INTERVAL 语法,它从当前时间开始计算截止时间。所以,要让用户从此刻起两周内有效,可以运行以下查询:

CREATE USER mark
IDENTIFIED WITH no_password
VALID FOR INTERVAL 2 WEEKS;

然后我们可以检查这个用户的有效期到什么时候:

SHOW CREATE USER mark
FORMAT LineAsString;

这个查询的输出会全部在一行里,所以我们手动格式化了一下,方便阅读:

CREATE USER mark 
IDENTIFIED WITH no_password 
VALID UNTIL '2026-09-18 10:06:29'

在修改用户时也可以使用这个语法。要让用户从此刻起一周内有效,可以运行以下查询:

ALTER USER mark VALID FOR INTERVAL 1 WEEK;
CREATE USER mark 
IDENTIFIED WITH no_password 
VALID UNTIL '2026-09-11 10:08:34'

流水线 SQL

贡献者:Alexey Milovidov

ClickHouse 26.8 引入了流水线 SQL,让你可以自上而下地写查询,每一步都接在前一步之后。

更多内容参见 Pipelined SQL in ClickHouse 26.8 博客文章(https://clickhouse.com/blog/pipelined-sql-26.8)。

将 ClickHouse 用作流式 HTTP API

由 Alexey Milovidov 贡献

ClickHouse 26.8 还引入了若干特性,让你能相当方便地为自己的表和常用查询套上一层轻量级 HTTP API。

更多内容参见 ClickHouse as a streaming HTTP API 博客文章(https://clickhouse.com/blog/clickhouse-streaming-http-api)。

system.user_query_log

由 Yue Ni、Alexey Milovidov 贡献

ClickHouse 26.8 还引入了一张新的系统表 system.user_query_log,其中只包含当前用户自己的查询。

也就是说,每个用户无需访问 system.query_log 表,就能查看自己的查询历史。

如果你的用户没有该表的访问权限,查询 system.query_log 仍会返回权限不足异常。

原子 POPULATE

由 Alexey Milovidov 贡献

增量物化视图相当于一个触发器:数据块插入表中时,就对它执行一次查询。

创建增量物化视图并在创建时填充数据时,曾存在一个竞态条件,会漏掉填充期间插入的记录。ClickHouse 26.8 已修复该问题。

调用 CREATE MATERIALIZED VIEW ... POPULATE 时,视图会订阅源表上的新插入,同时抓取现有数据的快照——这两步在源表短暂的排他锁下一起完成,因此在填充期间并发插入的每一行都能被投递且只投递一次。

该功能默认开启,把 materialized_views_populate_atomically 设为 0 即可关闭,这样就能重现之前的行为。

首先,创建一张包含 10 万行的源表:

CREATE TABLE src (id UInt64) 
ORDER BY id;
INSERT INTO src 
SELECT number FROM numbers(100000);

再创建一张目标表:

CREATE TABLE dst (id UInt64) 
ORDER BY id;

接下来,我们让一个查询插入 50 行,同时让另一个查询创建物化视图来填充 dst 表。

要想让某一行掉进空档,它的 INSERT 必须在 POPULATE 取源表快照时仍处于执行中。多数插入结束得太快,来不及被卡住,所以我们用 sleepEachRow 把 50 行摊到大约两秒半的时间里,并在这条插入还在运行时启动 CREATE。

我们还把 POPULATE 和 TO 一起使用,这在 26.8 之前属于语法错误。该视图会用 src 中已有的数据回填现有的 dst 表。

./clickhouse client -q "
  INSERT INTO src SELECT number + 100000 FROM numbers(50)
  WHERE sleepEachRow(0.05) = 0;" &

sleep 0.5

./clickhouse client -m -q "
  SET materialized_views_populate_atomically = 0;
  CREATE MATERIALIZED VIEW mv TO dst
  POPULATE AS SELECT id FROM src;"

wait

运行结束后,我们可以把源表和目标表对比一下:

SELECT (SELECT count() FROM src) AS sourceRows,
       (SELECT count() FROM dst) AS dstRows,
       (SELECT uniqExact(id) FROM dst) AS dstDistinct,
       sourceRows - dstRows AS lost,
       dstRows - dstDistinct AS duplicated
FORMAT PrettyCompact;
┌─sourceRows─┬─dstRows─┬─dstDistinct─┬─lost─┬─duplicated─┐
│     100050 │  100000 │      100000 │   50 │          0 │
└────────────┴─────────┴─────────────┴──────┴────────────┘

50 条记录全在源表里,目标表里一条都没有。这条插入在 mv 存在之前就开始了,所以没有向它推送;而它提交时,填充所用的快照已经拍完,所以回填也没看到它。

恰好是 50 条,是因为插入只在查询开始时决定一次数据要送往哪些视图,而不是逐行或逐块判断。所以整批插入要么全都到达,要么全都不到达。

如果我们删掉 mv、src 和 dst,再重建 src 和 dst,就可以创建物化视图,只是这次把 materialized_views_populate_atomically 设为 1:

./clickhouse client -q "
  INSERT INTO src SELECT number + 100000 FROM numbers(50)
  WHERE sleepEachRow(0.05) = 0;" &

sleep 0.5

./clickhouse client -m -q "
  SET materialized_views_populate_atomically = 1;
  CREATE MATERIALIZED VIEW mv TO dst
  POPULATE AS SELECT id FROM src;"

wait

这次统计每张表的记录数,会得到如下输出:

┌─sourceRows─┬─dstRows─┬─dstDistinct─┬─lost─┬─duplicated─┐
│     100050 │  100050 │      100050 │    0 │          0 │
└────────────┴─────────┴─────────────┴──────┴────────────┘

日语和中文分词器支持

贡献者:Robert Schulze、Amos Bird、Jimmy Aguilar Mena

ClickHouse 的默认分词器是 splitByNonAlpha(tokens、hasAllTokens 和 hasAnyTokens 函数都用它),它按空白和标点字符把字符串切分成子串数组。与英语等印欧语言不同,中文和日文文本的词之间没有空格,因此需要专门的分词器。

26.8 用两个专门打造的分词器解决了这个问题:

• japanese :日语分词器基于 MeCab 形态分析器,需要在服务端配置中指定外部 MeCab 词典

• chinese :jieba 风格的分词器,把词典与 HMM(隐马尔可夫模型)结合起来切分未知序列,例如把 ClickHouse是一个快速的开源数据库 切成 ClickHouse、是、一个、快速、的、开源、数据库,而不是整块或单个字符。

Japanese

要使用日语分词器,首先需要配置一部词典。这里我们使用 UniDic。从网站下载 .zip 压缩包后,还需要算出它的 SHA256,ClickHouse 会在加载前用它校验词典:

sha256sum /var/lib/clickhouse/unidic-cwj-202512.zip
d94216b589d15d05c408ed59abc5259086703ebbac14e225b5314e4cd106c4db

在 /etc/clickhouse-server/config.d/tokenizers.xml 中新增一个 tokenizer,定义自定义配置;服务器启动时,这份配置会合并进主 config.xml 文件。

<clickhouse>
  <tokenizer>
    <japanese>
      <dictionary_location>file:///var/lib/clickhouse/unidic-cwj-202512.zip</dictionary_location>
      <dictionary_sha>d94216b589d15d05c408ed59abc5259086703ebbac14e225b5314e4cd106c4db</dictionary_sha>
    </japanese>
  </tokenizer>
</clickhouse>

注意

也可以通过 HTTP/HTTPS URL 或 S3 兼容存储指定词典

如果服务器已经在运行,记得重启,让配置生效。现在可以创建文本索引并这样查询:

CREATE TABLE reviews
(
    id UInt64,
    text String,
    INDEX text_idx text TYPE text(tokenizer = 'japanese')
)
ENGINE = MergeTree
ORDER BY id;

INSERT INTO reviews VALUES
(1, '渋谷の新しい寿司屋で美味しいうにを食べた'),      -- "ate" (食べた)
(2, '大阪のラーメンは最高だった、また食べたい'),      -- "want to eat" (食べたい)
(3, '京都で抹茶アイスを食べながら散歩した'),          -- "while eating" (食べながら)
(4, '新幹線に乗って富士山を見に行った');              -- no mention of eating

SELECT id, text
FROM reviews
WHERE hasAnyTokens(text, ['食べ'], 'japanese')
ORDER BY id;

id

text

1

渋谷の新しい寿司屋で美味しいうにを食べた

2

大阪のラーメンは最高だった、また食べたい

3

京都で抹茶アイスを食べながら散歩した

返回 3 行。耗时:0.007 秒。

上例中,食べた、食べたい、食べながら 都是动词 食べる(“吃”)的不同形态,而分词器会把它们统统切分成词干 食べ 加一个独立的活用助词。因此只搜 食べ 这一个 token,就能正确命中第 1–3 行,跳过第 4 行。

更多细节请参阅日文分词器文档(https://clickhouse.com/docs/reference/engines/table-engines/mergetree-family/textindexes#japanese-tokenizer-dictionary)

中文

日文分词器需要下载外部分词典压缩包并在服务器 XML 配置里设置,中文分词器则不需要任何服务器配置。它内置的词典和隐马尔可夫模型数据(源自 cppjieba)直接编译进了 ClickHouse。

chinese 分词器允许指定粒度参数。默认值为 coarse_grained;如果传入 fine_grained,就能索引重叠的子词,提高搜索召回率,代价是索引更大。

下面的查询创建两张表。第一张表的索引使用 chinese 分词器,粒度参数为默认的 coarse_grained;第二张使用 fine_grained。

两张表都插入了四条字符串,其中 大学(“university”)要么单独出现(第 1 行),要么嵌在更长的复合词中(第 2、3 行),要么完全不出现(第 4 行)。

CREATE TABLE table_coarse
(
    key UInt64,
    str String,
    INDEX text_idx str TYPE text(tokenizer = chinese) -- default: coarse_grained
)
ENGINE = MergeTree ORDER BY key;

CREATE TABLE table_fine
(
    key UInt64,
    str String,
    INDEX text_idx str TYPE text(tokenizer = chinese('fine_grained'))
)
ENGINE = MergeTree ORDER BY key;

INSERT INTO table_coarse VALUES
    (1, '他考上了大学,很开心'), -- standalone 大学
    (2, '北京邮电大学的通信工程专业很强'), -- compound 北京邮电大学
    (3, '我毕业于北京大学计算机系'), -- compound 北京大学
    (4, '今天天气不错,适合散步'); -- no mention

INSERT INTO table_fine SELECT * FROM table_coarse;

下面的查询用 hasAllTokens 函数搜索 大学(“university”):先在 chinese 索引使用默认 coarse_grained 参数的表上查询,再在 fine_grained 参数的表上查询。

第一个表只返回了 他考上了大学,很开心 这一句,因为其中单独出现了 大学。第二个表既返回了单独出现 大学 的句子,也返回了包含复合词的句子:

SELECT
    key,
    str
FROM table_coarse
WHERE hasAllTokens(str, '大学')
ORDER BY key ASC;

Query ID: 7e348059-9cd1-4f72-8026-8d76266050e4

key

str

1

他考上了大学,很开心

1 row in set. Elapsed: 0.002 sec.

SELECT
    key,
    str
FROM table_fine
WHERE hasAllTokens(str, '大学')
ORDER BY key ASC;

Query ID: 4da23c89-8a10-4099-9637-bd2a14f6aa1b

key

str

1

他考上了大学,很开心

2

北京邮电大学的通信工程专业很强

3

我毕业于北京大学计算机系

3 rows in set. Elapsed: 0.002 sec.

这是因为 chinese 分词器在粗粒度模式下把 北京大学 和 北京邮电大学 当作词典中的单个词元,因此只搜索子词元「大学」时,粗粒度分词永远匹配不到这两行——尽管人读到句子时都知道这两句都与「大学」相关。fine_grained 模式则专门把这些复合词进一步拆成相互重叠的子词,如 北京、邮电 或 大学,所以只有它才能匹配到第 2 行和第 3 行。

新增分词器:icu 与 splitByRegexp

由 Jimmy Aguilar Mena 贡献

Jieba 面向简体和繁体中文,MeCab 主要用于日语,而 ICU(International Components for Unicode)是一个通用的、基于规则的多语言库,采用标准边界分析算法。那么对于泰语、老挝语、高棉语或缅甸语这类词与词之间不写空格的文字,又该如何分词呢?

26.8 版为 ClickHouse 新增了 icu(locale) 分词器,利用该库的 Unicode 分词功能把字符串切分成词元。对于词间不写空格的文字,ICU 采用基于词典的分词,确保文本被切成有意义的多字词,而不是单个字符。

在 26.8 之前,如果要用 asciiCJK 这类非 ASCII 分词器处理泰语、老挝语、高棉语或缅甸语文本,会遇到单字符碎片化的问题,因为 asciiCJK 把每个非 ASCII 字符都当作独立词元。以泰语词 บ้าน(“房屋”)为例:

SELECT tokens('บ้าน', 'asciiCJK');
┌─tokens('บ้าน', 'asciiCJK')─┐
│ ['บ','้','า','น']          │
└───────────────────────────┘

บ 和 น 是辅音字母,้ 是声调符号,า 是元音符号,所以分词把这个词切成了四个无意义的片段。hasAllTokens 只检查每个搜索片段是否出现在该行的某处,因此两个完全无关的真实泰语单词可以各自贡献一个片段,在搜索 "house" 时对完全无关的句子 "The horse is on the mountain" 产生误报:

-- "ม้าอยู่บนภูเขา" = "The horse is on the mountain" (no usage of "house")
SELECT tokens('ม้าอยู่บนภูเขา', 'asciiCJK');
┌─tokens('ม้าอยู่บนภูเขา', 'asciiCJK')──────────────────────┐
│ ['ม','้','า','อ','ย','ู','่','บ','น','ภ','ู','เ','ข','า'] │
└───────────────────────────────────────────────────────┘
SELECT hasAllTokens('ม้าอยู่บนภูเขา', 'บ้าน', 'asciiCJK');
┌─hasAllTokens⋯'asciiCJK')─┐
│                        1 │
└──────────────────────────┘
-- false positive

对比一下使用 icu 分词器并将 locale 设为 th 时会发生什么:

SELECT tokens('ม้าอยู่บนภูเขา', 'icu', 'th');
┌─tokens('ม้าอยู่⋯icu', 'th')─┐
│ ['ม้า','อยู่','บน','ภูเขา']  │
└──────────────────────────┘
-- "horse", "is/located", "on", "mountain"
SELECT hasAllTokens('ม้าอยู่บนภูเขา', 'บ้าน', 'icu(''th'')');
┌─hasAllTokens⋯u(\'th\')')─┐
│                        0 │
└──────────────────────────┘

提示

可以查询 system.collations 表,获取所有受支持的 ICU locale 列表:

对于需要更多控制的场景,26.8 引入了 splitByRegexp 分词器,可以用正则表达式作为分隔符把文本切分成 token。

ClickHouse 的默认分词器 splitByNonAlpha 会按每个非字母数字的 ASCII 字符切分,这意味着像 C++、C# 和 F# 这样的文本都会退化成单个字母:

SELECT
    tokens('C++', 'splitByNonAlpha'),
    tokens('C#', 'splitByNonAlpha'),
    tokens('F#', 'splitByNonAlpha')
FORMAT Vertical;
tokens('C++'⋯yNonAlpha'): ['C']
tokens('C#',⋯yNonAlpha'): ['C']
tokens('F#',⋯yNonAlpha'): ['F']

实际中,这意味着搜索 "C#" 可能返回像 "I am an expert in C++" 这样的误报:

SELECT hasAllTokens('I am an expert in C++', 'C#', 'splitByNonAlpha');
┌─hasAllTokens⋯yNonAlpha')─┐
│                        1 │
└──────────────────────────┘

此外,hasToken 会拒绝包含分隔符的搜索词,所以用 splitByNonAlpha 根本无法搜索字面词项 C++ 或 C#。

使用 splitByRegexp,可以显式定义分隔符模式,让字符 # 和 + 被视为单词的一部分:

CREATE TABLE hold_my_beer
(
id UInt64,
description String,
INDEX idx description TYPE text(tokenizer = splitByRegexp('[^\p{L}\p{N}#+]+'))
)
ENGINE = MergeTree ORDER BY id;

INSERT INTO hold_my_beer VALUES
    (1, 'I am an expert in C++'),
    (2, 'I am an expert in C#'),
    (3, 'I use Arch');
    
SELECT id, description FROM hold_my_beer WHERE hasAllTokens(description, 'C++') OR hasAllTokens(description, 'C#');
┌─id─┬─description───────────┐
│  1 │ I am an expert in C++ │
│  2 │ I am an expert in C#  │
└────┴───────────────────────┘

URL 数据库引擎

由 Alexey Milovidov 贡献

在上个月的 26.7 发布博客文章 中,我们介绍了 url 表函数和 URL 表引擎现在如何根据指定的 URL schema 分派到正确的后端,除了 HTTP,还支持文件路径、S3、GCS、Azure 和 HDFS。

26.8 引入了新的 URL数据库引擎,可以指定 URL 前缀,并把远程服务器上的任意路径作为表来查询。

在上个月的文章中,我们的示例展示了如何用 url 表引擎直接查询 s3 存储桶:

SELECT count(), avg(star_rating) FROM url('s3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet');

现在可以指定 s3://datasets-documentation/amazon_reviews 作为前缀,并把存储桶中的每个文件作为单独的表来查询:

CREATE DATABASE datasets
ENGINE = URL('https://datasets-documentation.s3.eu-west-3.amazonaws.com/amazon_reviews/');
USE datasets;

SELECT count() FROM 'amazon_reviews_2015.snappy.parquet';
┌──count()─┐
│ 41905631 │ -- 41.91 million
└──────────┘
SELECT count() 
FROM 'amazon_reviews_2014.snappy.parquet';
┌──count()─┐
│ 44127569 │ -- 44.13 million
└──────────┘

在 clickhouse-local 中,默认数据库现在也叠加在 URL 之上,方便你查询本地文件、URL、S3 数据,或默认数据库中的普通表:

SELECT * FROM 'hits.tsv';
SELECT * FROM 'https://example.com/hits.tsv';
SELECT * FROM 's3://mybucket/hits.tsv';
SELECT * FROM table;

bigquery 表函数和 BigQuery 表引擎

贡献者:Alexey Milovidov

对于还没把工作负载从 BigQuery 迁移到 ClickHouse 的用户,26.8 引入了 bigquery 表函数和 BigQuery 表引擎,让迁移比以往更容易。

我们用一个现成的 Stack Overflow 帖子 BigQuery 项目来看看它如何工作(设置步骤)(https://pastila.nl/?003f30a0/ab5c593a768497695e7e0c9957cf118d#2FvhCYiX4UryqoULfQ/vfA==GCM)。

先使用 bigquery 表函数看看数据形态。为此需要向 bigquery 表函数传入服务密钥。

创建一个命名集合,将下面的 your_service_key 替换为从 Google 控制台获取的 .json 服务密钥内容:

<clickhouse>
    <named_collections>
        <bigquery_credentials>
            <project>bigquery-clickhouse</project>
            <dataset>stackoverflow</dataset>
            <table>badges</table>
            <service_account_key><![CDATA[your_service_key]]></service_account_key>
        </bigquery_credentials>
    </named_collections>
</clickhouse>

确认命名集合已存在:

SELECT *
FROM system.named_collections;
┌─name────────┬─collection───────────────────────────────────────────────────────────────────┬─source─┬─create_query─┐
│ my_bigquery │ {'dataset':'[HIDDEN]','project':'[HIDDEN]','service_account_key':'[HIDDEN]'} │ CONFIG │              │
└─────────────┴──────────────────────────────────────────────────────────────────────────────┴────────┴──────────────┘

现在把命名集合作为 bigquery 表函数的参数,查看数据形态:

DESCRIBE TABLE bigquery(bigquery_credentials);
Query id: dd1e8285-b286-4892-8770-eeed49ef6919

┌─name─────┬─type───────────────────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ Id       │ Nullable(Int64)                │              │                    │         │                  │                │
│ UserId   │ Nullable(Int64)                │              │                    │         │                  │                │
│ Name     │ Nullable(String)               │              │                    │         │                  │                │
│ Date     │ Nullable(DateTime64(6, 'UTC')) │              │                    │         │                  │                │
│ Class    │ Nullable(Int64)                │              │                    │         │                  │                │
│ TagBased │ Nullable(Int64)                │              │                    │         │                  │                │
└──────────┴────────────────────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘

6 rows in set. Elapsed: 0.602 sec.

现在可以轻松在本地创建同样的表并插入数据:

CREATE TABLE bq_badges
(
    Id       Int64,
    UserId   Int64,
    Name     LowCardinality(String),
    Date     DateTime64(6, 'UTC'),
    Class    Int64,
    TagBased Int64
)
ENGINE = MergeTree
ORDER BY (Id);

INSERT INTO bq_badges SELECT * FROM bigquery(bigquery_credentials) LIMIT 5; -- I don't want to max out my credit card

SELECT * FROM bq_badges;
┌───────Id─┬───UserId─┬─Name────────┬───────────────────────Date─┬─Class─┬─TagBased─┐
│  3336768 │  1033808 │ Copy Editor │ 2012-05-03 22:19:43.187000 │     1 │        0 │
│  6687355 │    19299 │ .net        │ 2013-06-15 03:03:52.690000 │     1 │        1 │
│ 12885730 │  3892259 │ Copy Editor │ 2015-01-31 14:43:59.373000 │     1 │        0 │
│ 39830489 │ 10659482 │ Copy Editor │ 2020-12-09 11:16:11.410000 │     1 │        0 │
│ 40413130 │  1386551 │ Copy Editor │ 2021-01-29 18:00:54.783000 │     1 │        0 │
└──────────┴──────────┴─────────────┴────────────────────────────┴───────┴──────────┘

5 rows in set. Elapsed: 0.005 sec.

S3 Tables

贡献者:Konstantin Vedernikov

ClickHouse 26.8 为 Amazon S3 Tables 增加了写入支持,这是 AWS 面向 Iceberg 表的托管服务。除了查询现有表,现在还可以插入数据、创建新表。

首先,启用 Iceberg catalog 集成和写入:

SET allow_database_iceberg = 1;
SET allow_insert_into_iceberg = 1;

配置好可访问表存储桶的 AWS 凭证后,就可以使用 DataLakeCatalog 数据库引擎连接。把下面的区域和 warehouse ARN 替换成你自己的:

CREATE DATABASE tables
ENGINE = DataLakeCatalog(
    'https://s3tables.us-east-1.amazonaws.com/iceberg'
)
SETTINGS
    catalog_type = 's3tables',
    region = 'us-east-1',
    warehouse = 'arn:aws:s3tables:us-east-1:123456789012:bucket/analytics';

然后可以列出可用的表并查询其中一个。例如,如果你的存储桶在 ns 命名空间下有一个 events 表:

SHOW TABLES FROM tables;

SELECT *
FROM tables.`ns.events`
LIMIT 10;

现在也可以向该表写入数据,提供与其 schema 匹配的值:

-- Replace … with values matching your table's columns.
INSERT INTO tables.`ns.events` VALUES (…);

Snowflake Horizon

贡献者:Melvyn Peignon

ClickHouse 26.8 新增通过 Snowflake Horizon catalog 读写 Iceberg 表的支持。ClickHouse 直接从对象存储读取底层数据文件。

我们先启用 Iceberg catalog 集成和写入功能,再连接到该 catalog。请把下面的账户端点、数据库名、个人访问令牌和 Snowflake 角色换成你自己的。该角色需要有权访问你要使用的 Iceberg 表。

SET allow_database_iceberg = 1;
SET allow_insert_into_iceberg = 1;

CREATE DATABASE horizon
ENGINE = DataLakeCatalog(
    'https://<org>-<account>.snowflakecomputing.com/polaris/api/catalog'
)
SETTINGS
    catalog_type = 'horizon',
    warehouse = 'ICEBERG_DB',
    catalog_credential = '<PAT>',
    auth_scope = 'session:role:<ROLE>',
    vended_credentials = 1;

接下来可以列出可用的表,并查询其中一个。例如,如果你的 catalog 在 schema 命名空间下有一个 trades 表:

SHOW TABLES FROM horizon;

SELECT *
FROM horizon.`schema.trades`
LIMIT 10;

要插入数据,请提供与该表 schema 匹配的值:

-- Replace … with values matching your table's columns.
INSERT INTO horizon.`schema.trades` VALUES (…);

ClickHouse 通过 Horizon catalog 提交这些更改。

Puffin 文件格式

由 Konstantin Vedernikov 贡献

ClickHouse 26.8 新增对 Puffin 文件格式的支持,Apache Iceberg 用它来存储统计信息和删除向量。

下面用 ClickHouse 测试套件中的一个小样本文件看看它是怎么工作的:

SELECT referenced_data_file, deleted_rows
FROM url(
    'https://raw.githubusercontent.com/ClickHouse/ClickHouse/693dee22dda0d7ff23343c326754ccfc24f3237f/tests/queries/0_stateless/data_puffin/file_properties_ok.puffin',
    'Puffin'
);
┌─referenced_data_file───────────┬─deleted_rows─┐
│ /data/table/part-00000.parquet │ [2,5]        │
└───────────────────────────────┴──────────────┘

这说明所引用的 Parquet 文件中第 2 行和第 5 行被标记为已删除。我们无需访问那个 Parquet 文件——删除信息就存放在 Puffin 文件自身里。这有助于解释为什么数据文件中存在的行,在查询 Iceberg 表时却不出现。

也可以用 PuffinMetadata 格式查看该 blob 的类型和属性:

SELECT blob_type, properties
FROM url(
    'https://raw.githubusercontent.com/ClickHouse/ClickHouse/693dee22dda0d7ff23343c326754ccfc24f3237f/tests/queries/0_stateless/data_puffin/file_properties_ok.puffin',
    'PuffinMetadata'
);

对这个文件来说,blob 类型是 deletion-vector-v1,其属性中的 cardinality 为 2,与上面两个被删除的行位置一致。

Iceberg 中预取 manifest 文件

由 Asya Shneerson 和 Konstantin Vedernikov 贡献

从 Iceberg 表读取数据之前,ClickHouse 要先读取描述其数据文件和删除文件的 manifest 文件。抓取并处理这些元数据会明显增加启动耗时,尤其是在需要向对象存储发起大量请求时。

在 26.8 中,ClickHouse 会在解析当前 manifest 文件的同时预取下一个,让存储读取与 CPU 计算重叠进行。

删除 manifest 也是并发读取和解码的。由于这些文件必须在读取数据文件之前处理完,这一改动能加快含大量删除文件的表的查询启动速度。iceberg_delete_manifest_decode_concurrency 设置控制同时解码多少个删除 manifest,默认值为 4。

本次发布还修复了数据湖 catalog 的 S3 bucket 区域缓存,避免反复发请求来确定 bucket 所在区域。

原生 Parquet 改进

由 Alexey Milovidov 和 Vasily Chekalkin 贡献

ClickHouse 26.8 对 Parquet 读取做了多项改进,帮助查询跳过不必要的数据。

对于带有 ORDER BY 和 LIMIT 的查询,ClickHouse 可以先读取排序和过滤所需的列,然后只为通过 LIMIT 筛选后保留下来的行获取其余列。这项优化默认开启。

下面从公开 Parquet 数据集中找出最新的十个事件,用 WatchID 打破并列:

SELECT URL, Title
FROM s3(
    'https://clickhouse-public-datasets.s3.amazonaws.com/hits_compatible/hits.parquet',
    NOSIGN
)
ORDER BY EventTime DESC, WatchID DESC
LIMIT 10
SETTINGS query_plan_optimize_lazy_materialization_for_object_storage = 1;

我们可以把它与关闭惰性读取的情况对比:将 query_plan_optimize_lazy_materialization_for_object_storage 设为 0。在 ClickHouse 26.8.2.7 上反复测试时,关闭该优化后查询从 S3 读取约 6.6–6.7 GB,开启后读取 1.5 GB,返回的是同样的十行。

基于字典的过滤也能帮助 ClickHouse 在等值和 IN 条件下跳过数据。下面查找匹配某一款手机型号的行:

SELECT count()
FROM s3(
    'https://clickhouse-public-datasets.s3.amazonaws.com/hits_compatible/hits.parquet',
    NOSIGN
)
WHERE MobilePhoneModel = 'GT-C3262';
┌─count()─┐
│     200 │
└─────────┘

当某个列块完全采用字典编码时,如果请求的值不在字典中,ClickHouse 就可以跳过该行组。即使 min/max 统计信息无法排除匹配,并且布隆过滤器不可用,这项优化仍然有用。

开启字典过滤后,该查询处理了 12 个数据页;关闭时则处理 226 个。两次查询都返回 200。input_format_parquet_dictionary_filter_push_down 设置默认为 1048576(即字典页上限为 1 MiB);将其设为 0 会关闭这项优化。

GeoParquet 查询也能受益于空间剪枝。ClickHouse 利用边界框信息跳过无关的行组和页,并在读取行时应用空间谓词。

GROUP BY 性能改进

由 Nihal Z. Miaji、Dmitriy Terenichev、Konstantin Bogdanov、Harikrishnan Prabakaran 贡献

26.8 版本还对 GROUP BY 做了一系列性能改进,包括:

• 一种新的并行 GROUP BY 算法,自适应地结合了合并聚合器和拆分聚合器所用的方法。

• 26.7 版本为按键排序的表将 GROUP BY 与 ORDER BY LIMIT 融合。26.8 对任意读取顺序都支持这样做,并剪掉不可能出现在结果中的分组。

• 以单个字符串为键的 GROUP BY 现在使用小得多的哈希表单元。

• 并行 GROUP BY 查询的最后合并步骤现在使用多线程,避免成为单线程瓶颈。

我们将在另一篇文章中更详细地介绍这些优化。

联接

由 Han Fei, Anton Popov, Robert Schulze, Alexey Milovidov, Vladimir Cherkasov, Alexander Gololobov 贡献

和每次发布一样,这次我们在 join 方面也有不少改进:

• 对于小表,列统计信息现在默认在 INSERT 时构建,全部 TPC-H 基准测试的成绩因此提升了 29%。

• 连接条件为两个不等式的 JOIN 过去会按带过滤的 CROSS JOIN 执行,现在改用基于排序的 IEJoin 算法。

• 新增 merge join 算法 parallel_full_sorting_merge ,可以利用所有核心。输入按 key 的哈希分片,各分片独立执行 merge join。

• 面向分布式查询计划的基于代价的优化器。该优化器借助基数估计,决定分布式 join、聚合、排序和数据搬移该如何执行。

这些功能的更多细节,我们会另写一篇文章介绍。

关于我们

ClickHouse(clickhouse.com) 是面向 AI 时代打造的高性能实时分析数据库,能够以极致性能处理海量数据分析任务。凭借高并发、低延迟和云原生架构,ClickHouse 广泛应用于可观测性、数据仓库、实时分析及 AI 数据基础设施等场景。我们致力于帮助企业在公有云平台上构建安全、弹性且高性价比的实时分析与 AI 数据平台,加速释放数据价值,推动智能化创新与数字化转型。目前,Trip.com、DiDi、Meta、Sony、Netflix、Deutsche Bank、Sierra、Cloudflare 等全球领先企业均在使用 ClickHouse 支撑其关键业务和数据分析平台。

【YOLOv8系列】YOLOv8的webUI界面设计;通过Streamlit实现YOLOv8的可视化交互界面设计 但是我为了避免重复性的工作,且为了避免重复安装之前(安装pytorch和yolov8时)已经安装好的库,因此写了一个python脚本进行安装;需要提前在有网络连接的电脑上下载所有必要的依赖项,然后将这些文件传输到离线的机器上进行安装。脚本将自动跳过已安装的包,并安装其余的 .whl 文件。在离线的机器上,切换到包含下载好的文件的目录。证明我们的streamlit安装成功了。证明你的streamlit安装成功了。第一步:在有网络连接的电脑上下载。第二步:将下载的文件传输到离线机器。文件)传输到离线的机器上。 阅读详情

相关推荐

ABP框架实战:从零搭建多租户应用(含完整代码示例)

本文详细介绍了如何使用ABP框架从零构建多租户SaaS应用,涵盖多租户架构设计、数据隔离实现、租户管理及性能优化等核心内容。通过完整的代码示例,帮助开发者快速掌握企业级数据隔离系统的开发技巧,提升SaaS应用开发效率。

weixin_29247219的博客 262

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 191

STM32开发者必看:如何在正点原子探索者开发板上快速移植CANopenNode协议栈

本文为STM32开发者提供了在正点原子探索者开发板上快速移植CANopenNode协议栈的实战指南。文章详细介绍了从环境准备、硬件抽象层适配到协议栈初始化与测试的全过程,并分享了PDO配置与性能优化等关键技巧,帮助开发者高效实现CANopen标准化通信。

weixin_29173777的博客 462

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 114

比亚迪璇玑架构:10ms级响应引领智能驾驶革命

比亚迪璇玑架构通过三大创新,实现10ms级控制响应时延,使AEB刹车距离比竞品缩短20米。

百态·数智思维 | 聚焦大数据、量化与未来AI 1255

【比较器仿真】

比较器tran noise、pnoise仿真、噪声仿真、MC失调仿真

pickweb的博客 1万+

在Codex 让AI模型 拥有长期智能记忆

本文介绍Claude-Mem V15新功能——智能记忆召回,解决AI遗忘、重复提示、执行不一致等问题。通过本地部署claude-mem,实现自动记录决策(如数据库选型)、跨会话智能召回,支持记忆写入、检索、遗忘全流程闭环。相比传统记忆方案,其基于Hooks自动捕获工具调用,结构化存储,可追溯、可共享、可清理,显著提升工程效率与协作一致性,是长期项目中理想的“工作黑匣子”与“工程脑”。

米莱虾 257

Human3.6M 数据集介绍及下载

360 万张 3D 人体姿势和对应图像11 名专业演员(6 男 5 女)7 个场景(讨论、吸烟、拍照以及打电话等等)

XavierJ的博客 3万+

Docker Compose:搭建本地多服务开发环境

从一个 Java API、PostgreSQL 和 Redis 开始,配置服务名、端口、环境变量、健康检查、数据卷和依赖关系。理解 Compose 文件如何被解析、项目如何隔离,以及哪些数据不能依赖“重建容器”保留,能够把个人开发环境整理成团队可复用的启动入口。

m0_62221377的博客 347

OMNET++ INET框架学习教程(一)

在自组网学习的道路上摸石头过河,帮你快速入门OIMNET++平台下的INET框架。

NLDwangzhe的博客 6560

S32K144 ADC硬件触发+DMA传输实战:从寄存器配置到数据采集全流程

本文详细解析了S32K144微控制器中ADC硬件触发与DMA传输的协同工作机制,提供了从寄存器配置到数据采集的全流程实战指南。通过PDB定时触发ADC转换,并利用DMA实现数据自动搬运,构建了高效、实时的汽车级数据采集系统,有效释放CPU资源,满足汽车电子应用的严苛要求。

weixin_29194693的博客 474

AI全栈实战 | 3.9-01 爬虫入门:requests 加 BeautifulSoup 三分钟跑通,但 90% 的人栽在这 4 个“礼貌“问题上

⚠️:本文内容仅用于。请遵守目标站点的服务条款与相关法律法规,不得对目标服务造成负担,不得采集、传播个人隐私数据。技术是中性的,边界在你手里。爬虫的入门技术(requests 发请求 + BeautifulSoup 解析)三分钟就能学会。真正区分"会用爬虫"和"会做爬虫的人"的,是这篇我们跑通"请求→解析→存储"的最小闭环,然后重点把"合规与礼貌"这根弦给你绷上。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 363

NSIS教程(2): 传统用户界面(Classic UI)

NSIS教程: 《NSIS用户手册 中文版》 《NSIS图文教程集锦 - 轻狂志》 本文以一个完整的、传统界面的网易云音乐安装包的脚本为示例,来介绍NSIS传统用户界面的开发流程。 NSIS脚本 # 单行注释用井号"#"或分号";",跨行注释用可以用C/C++中注释语法。 # 使用!define定义一些常量(如安装包的版本号等) # 对常量或变量的引用可以使用如${PROD

while(1) { smile(); } 8万+

45-存储过程与函数

匿名块跑完就没了,想下次再用只能复制粘贴。给块起个名字存进数据库,就成了存储过程与函数:一次编译、处处调用、权限收口,还能让 Java 侧少拼 SQL。这篇讲封装、调用、限制与排错的完整套路。CREATE OR REPLACE 覆盖式创建,事务由调用方控制;参数三模式 IN 只进、OUT 只出、IN OUT 双向,OUT 参数调用时要备好变量接;调用三姿势 EXEC、CALL、匿名块,命名传参=>最清晰;函数必有 RETURN,想在 SQL 里调用就不能碰 DML 和事务控制;

yuhou25的博客 152

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 393

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

数据库主键选型指南:BIGINT vs VARCHAR

主键选型关乎数据库性能与架构演进。BIGINT(如雪花算法)在顺序写入、二级索引开销和分布式生成上优势显著,适合高并发核心链路;而传统 VARCHAR UUIDv4 因随机性导致频繁页分裂、存储膨胀,性能堪忧。UUIDv7 通过时间戳有序性实现高效追加写入,结合 BINARY(16) 存储可兼顾性能与安全,成为现代微服务新选择。关键在于:主键应稳定、无业务含义,优先选用趋势递增的紧凑类型,并根据场景合理采用双主键模式或 ULID 等替代方案。

小李同学的博客 299

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

自动化运维选型:四条技术路线的能力边界,以及它们为什么不能互相替代

自动化运维怎么选型?拆解配置管理、基础设施即代码、作业调度与场景化编排四条技术路线边界,分析账本归属与时间语义差异,给出四种架构组合与判断点,帮企业看清为何不能互相替代。

trainsignalcn的专栏 306

不用再为文本搜索单独维护一套系统!全文检索深度解析

为了给商品、客服工单或者企业知识库增加一个搜索框,企业往往需要在业务数据库之外,再部署一套Elasticsearch。数据库保存商品、订单和用户等真实业务数据,搜索引擎保存另一份文本索引;两套系统之间,还需要通过CDC、消息队列或者同步程序持续传输数据。一个看似简单的搜索需求,最后可能变成两套集群、两份数据和一条必须保持稳定的数据链路。由此产生的问题并不少:数据库已经完成更新,搜索结果却可能尚未同步;业务查询同时涉及文本、库存、权限和订单状态时,应用需要在两个系统之间来回组合结果;

TiDB 社区干货传送门 185

48-逻辑结构表空间段区块

默认 10%,意思是块里的空闲空间低于 10% 时就不再插入新行,留着给已有行的 UPDATE 变胖用。注意 INSERT 过程中每次申请新区,都是一次潜在的空间报错点,如果表空间满了,此刻就会抛 ORA-01653。剩下的空间被谁占了?段的每个区可以落在表空间的任一数据文件,所以 2T 的表在 32G 单文件上限(smallfile)的世界里照样能活——多加文件就行。,一张只有两个 CLOB 字段的表,实际在库里是三个段(表段 + 两个 LOBSEGMENT),空间统计漏算 LOB 段是新手常犯的错。

yuhou25的博客 283

市场调查与统计分析专业大学期间考证怎么安排?

市场调查与统计分析专业的考证规划,适合从一份完整的调查报告倒推:能不能设计问卷、判断样本是否合理、清洗数据,再把分析结果转化为业务建议?围绕这条能力链安排证书,比单纯按“热门程度”报名更有针对性。结合2026年的学习安排,并为2027年的实习、升学和求职预留时间,大学期间可以重点考虑六类证书:全国计算机等级考试证书、大学英语四级或六级成绩报告单、CDA数据分析师、初级统计专业技术资格证书、微软办公软件国际认证中的Excel相关证书,以及软考数据库系统工程师资格证书。

cc572502653的博客 157

QT(了解各个控件及布局)下

练习工程里加一个“确认发送”按钮点击后弹出一个自己写的对话框:一句提示 + “确定”/“取消”确定 → 打印“已确认”,继续发送;取消 → 打印“已取消”,不发送点窗口右上角 X = 取消对话框弹出期间,主窗口点不动(模态)首先我们要在原项目的基础上,新建一个类,就是一个新的小对话框窗口,如下:然后系统会帮我们创建这个新类的头文件和源文件,接着我们到利用ui编辑器设计这个新窗口的界面,如下:如果要实现文字居中,就要设置到QLabel的属性设置这个alignmen为水平中心对齐。

lhbweilai的博客 213

Oracle 19c 在线重定义后旧表空间清理及 ASM 存储资源回收 SOP

Oracle 19c 在线重定义后旧表空间清理与 ASM 存储资源回收 SOP

「YYL DBA手记」 数据库 · 架构 · 运维 · 实战 yyldba.blog.youkuaiyun.com 478

AI Agent记忆从不是向量库:Oracle拆解读写分离与记忆晋升门,终结无脑存聊天的伪智能——读Wojtek Pluta演讲

在过去一年里,绝大多数团队在为自己的 AI Agent 增加“记忆能力”时,做法几乎如出一辙:开一个向量数据库(Pinecone / Milvus / Chroma),在每轮对话结束时,把用户的提问和 Agent 的回复转成 Embedding 向量直接往里塞;<summary> 审查 Kyle 的贷款完整性,审批未通过,等待补件。这种记忆能力完全脱离了脆弱的会话上下文窗口,靠的是数据库底座驱动的显式记忆装配。在写路径中,决定一条信息能否从“临时上下文”跃升为“长期持久化记忆”的核心关卡,正是。

鲜衣怒马楼兰月 126

从事件风暴到因果收敛:Mopheus多智能体协同事件触发架构与防循环实践

在构建生产级多智能体协同引擎的过程中,我们总结了三条核心工程准则:1.不可变因果链优于事后关系反查在高度并发且异步的多智能体网络中,因果关系的追溯绝不能依赖事后查库反查关联;将只增的因果祖先链显式封装在事件载荷与任务上下文中,以O(1)的内存检查实现确定性极高的闭环防范。2.生产端纯粹广播与消费端前置极速过滤是高吞吐的基石遵循严格的Pub/Sub模式,让核心业务实体与下游智能体编排解耦;通过调度层内存条件字典求值(conditions),在纳秒级内过滤掉99%的无关事件,保障零业务侵入与极高的系统吞吐。

weixin_54551388的博客 237

Spring事务和事务传播机制

3. 可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同⼀事务多次查询的结果⼀致, 但是其他事务新插⼊的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.p1事务可以认为是⽗事务, 嵌套事务是⼦事务. ⽗事务出现异常, ⼦事务也会回滚, ⼦事务出现异常, 如果不进⾏处理, 也会导致⽗事务回滚.

txxzjmzlh的博客 202

布隆过滤器(Bloom Filter)入门与实战:它是什么、怎么用、有什么坑

📌 先说结论

nice_lcj520的博客 463
上一篇: ClickHouse 托管 Postgres 的 WAL 背压机制与实现原理
下一篇: ClickHouse Grafana 插件更新:引入无代码查询与日志检索优化
ClickHouseDB
博客等级 码龄3年 1707粉丝 320原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值