337p人体粉嫩胞高清图片,97人妻精品一区二区三区在线 ,日本少妇自慰免费完整版,99精品国产福久久久久久,久久精品国产亚洲av热一区,国产aaaaaa一级毛片,国产99久久九九精品无码,久久精品国产亚洲AV成人公司
網易首頁 > 網易號 > 正文 申請入駐

DuckDB 開發者大會四連擊:擴展,加密,存儲過程,邊緣分析

0
分享至

DuckDB 最近舉辦了首屆 DuckDB 開發者大會,里面有四個有趣的議題,老馮這里從視頻中提取了文字稿,然后請 Claude / GPT 整理成完整的文章,在這里與大家分享,看看 DuckDB 生態的最新進展。以及最后附上老馮對 DuckDB 生態的點評

四篇演講分別是:

DuckDB 擴展:過去、現在、與未來

DuckDB 中的存儲與加密

DuckPL:DuckDB 中的一種存儲過程語音(PL/PGSQL)

GizmoEdge:用于物聯網的分布式 DuckDB 引擎

DuckDB 擴展:過去、現在與未來 引言

大家好,我是 Sam Ansmink。今天我將為大家介紹 DuckDB 擴展。今天上午 Rusty 已經深入講解了擴展開發的細節,而我會從更高層次來審視 DuckDB 擴展的全貌——回顧它的發展歷程,了解當前狀態,并展望未來方向。

今天的內容分為三個部分:首先是簡介,讓大家對 DuckDB 擴展有基本了解;然后我們會回顧過去,看看整個擴展框架和生態系統是如何一步步發展起來的;接著是現在,了解當前的最佳實踐和現有功能;最后我會分享一些未來的規劃和發展方向。

自我介紹

我是 Sam Ansmink,在 DuckDB Labs 工作已經超過四年了。在加入 DuckDB Labs 之前,我在阿姆斯特丹的 CWI(荷蘭國家數學與計算機科學研究中心)完成了碩士論文——那里正是 DuckDB 的誕生地。CWI 有一個數據庫架構研究組,我的碩士論文課題是在 DuckDB 中實現加密查詢執行。

畢業后我加入了當時還是一家小型創業公司的 DuckDB Labs,參與開發了多個擴展,同時也深度參與了擴展框架本身的建設,包括擴展模板、各種 API 以及用于部署和測試的 CI/CD 流水線。

什么是 DuckDB 擴展?

DuckDB 擴展本質上是一種為 DuckDB 核心功能添加或修改功能的方式。它可以實現很多東西:表函數、數據類型、文件系統、目錄、加密模塊等等。

舉幾個例子:JSON 擴展可以幫你讀取 JSON 文件;PostgreSQL 擴展可以與 PostgreSQL 數據庫集成;還有一些更有趣的社區擴展,比如 Google Sheets 擴展,可以直接從 Google 表格讀寫數據。當然也有一些比較小眾的擴展,這也是科學研究的常態。

為什么需要擴展?

這個問題很關鍵,我認為主要有以下幾個原因:

二進制文件大小:DuckDB 是一個嵌入式數據庫,我們希望它能在任何地方運行。如果二進制文件達到 3GB,那就成問題了,因為我們也需要在存儲和內存受限的環境中運行。通過擴展機制,用戶可以自行決定功能集和二進制大小之間的平衡。

零依賴:你可能聽說過 DuckDB 是零依賴系統。這是真的,但我們確實想利用很多優秀的外部庫。解決方案就是把這些依賴推到擴展里。DuckDB 核心保持零依賴,而擴展則可以使用這些依賴來實現特定功能。只有當你需要某個功能時,才會引入相應的外部依賴。

功能不兼容:有些功能之間存在互斥性。比如不同的 SQL 方言可能相互不兼容,擴展是處理這種情況的好機制。

不同的維護者:不同的人可以維護不同部分的代碼,這也是擴展機制帶來的靈活性。

如何使用擴展?

即使你認為自己沒有使用 DuckDB 擴展,實際上你可能已經在用了。DuckDB 會自動安裝和加載擴展。

舉個例子,當你執行一條簡單的查詢,從網絡上的 JSON 文件中 SELECT * 時,DuckDB 會在后臺自動為你安裝和加載兩個必需的擴展(HTTP 文件系統擴展和 JSON 擴展)。這個過程完全透明,你甚至不會注意到。當然,你也可以選擇手動安裝和加載擴展。

擴展從哪里獲取?

我們有一個叫做"擴展倉庫"的概念,目前有兩個倉庫:Core(核心)Community(社區)。核心倉庫包含所有由 DuckDB 官方維護的擴展,社區倉庫則由社區成員維護。

使用起來非常簡單,直接用 SQL 就可以安裝。默認從核心倉庫安裝,如果想安裝社區擴展,只需指定 FROM community 即可。

發展歷程回顧

讓我們來看看 DuckDB 擴展的發展歷程:

?2018年:DuckDB 在 CWI 的第一次代碼提交?2020年:擴展機制誕生——這是 DuckDB 能夠將代碼放入擴展并加載的核心能力,至今仍是 DuckDB 加載擴展的基礎方式?2021年:核心倉庫建立——用戶可以通過 INSTALL 語法自動安裝擴展?2023年:C++ 擴展模板發布——這是一個關鍵節點,我們不僅自己能構建擴展,還告訴社區"你們也可以這樣做"。這個模板現在被大多數核心擴展和社區擴展使用?2024年:社區倉庫建立——讓社區開發者能夠輕松部署擴展,用戶安裝社區擴展和核心擴展一樣方便?之后:Rust 擴展模板和 C 擴展模板相繼發布

在擴展方面,第一個重要擴展是 ICU(國際組件庫),它是一個相當大的庫,正是因為它太大了無法放入核心,才催生了擴展機制。之后陸續出現了 Parquet、HTTP 文件系統、PostgreSQL、Delta Lake 等擴展,最近還有去年發布的 DuckLake 擴展,實現了我們自己的開放湖倉格式。

現狀

DuckDB 擴展現在非常普及。看一些數據:

?32 個核心擴展?145 個社區擴展?核心擴展每周下載超過 2700 萬次?社區擴展每周下載超過 50 萬次

與 DuckDB Python 客戶端的下載量相比,這些數字也相當可觀。這說明 DuckDB 擴展已經成為使用 DuckDB 不可或缺的一部分,這當然也與我們的自動加載機制有關,很多人確實依賴 Parquet、HTTPS 等功能。

當前的擴展構建方式

目前我們有三種擴展模板:

1.C++ 擴展模板(推薦):使用 DuckDB 的不穩定 API2.Rust 擴展模板(實驗性):理論上很好但有一些局限,目前也基于不穩定 API3.C 擴展模板:支持 C 和 C++,是第一個使用穩定 API 的模板

關于維護者,核心倉庫中的擴展分為三類:

?主要核心擴展:獲得 DuckDB Labs 最高級別支持?次要核心擴展:可能更實驗性,支持力度稍小?第三方核心擴展:由 DuckDB Labs 的合作伙伴維護

社區倉庫的擴展則由社區成員維護。

當前面臨的挑戰

我們的主要推薦方式是使用不穩定的 C++ API,這帶來一些問題:

?每個版本都需要重新構建所有擴展:這是一個負擔?擴展維護成本高:每當 DuckDB 核心工程師修改了被很多擴展使用的 API,就會破壞這些擴展,維護者需要花時間修復?難以編寫文檔:API 是一個不斷變化的目標,要么投入大量精力更新文檔,要么文檔就會過時

未來方向

解決方案是使用穩定的 C API。穩定 API 帶來的好處顯而易見:

?穩定性:編譯一次的擴展可以在多個版本上持續工作?良好的互操作性:作為 C API,可以更好地與 Rust 等其他語言集成?擴展維護者可以構建擴展后"放心忘記",它會持續工作

我們的目標是:

1.擴展 C 擴展 API 的功能:目前正在努力添加更多特性,以便更多擴展能夠遷移過來2.穩定化 Rust 和 C 擴展模板:利用日益強大的穩定 API3.盡可能多地遷移現有擴展:評估哪些適合用 Rust,哪些適合用 C/C++

時間表方面,雖然我們不傾向于公開承諾日期,但內部目標是在 v1.6 實現這些主要改進(v1.5 將在幾周后發布,v1.6 預計在幾個月后,大約今年夏天)。

問答環節要點

關于私有擴展倉庫:DuckDB 已經支持這個功能。你可以將 DuckDB 設置為無簽名模式,從任意位置安裝和加載擴展;或者編譯你自己的 DuckDB 版本,把閉源擴展靜態鏈接進去。

關于 Iceberg 擴展的分區寫入支持:這是高優先級的功能,預計在 V2 支持完成后就會著手,可能在 v1.5 的某個 bug 修復版本中就能實現。

關于安全性:默認模式下 DuckDB 會自動加載擴展,這是為了最佳的開箱體驗。但如果你構建的是安全關鍵系統,可以參考我們的"Securing DuckDB"文檔,比如編譯自己的版本并靜態加載擴展、禁用擴展安裝等。

關于社區擴展的安全審計:首先,自動加載只對 DuckDB 核心團隊控制的擴展有效,我們永遠不會自動加載社區擴展。社區擴展的安全管理方式與其他包管理器類似——用戶需要自己評估是否信任某個擴展。所有社區擴展都必須開源,你不能直接上傳二進制文件到社區倉庫。這需要社區的共同檢查,我們也會主動排查惡意擴展。

總結

?DuckDB 擁有相當完善的擴展生態系統?擴展下載量巨大,維護者社區不斷壯大,提供了各種我們從未想到過的功能?目前推薦的 C++ API 能深入 DuckDB 內部,但代價是不穩定?我們正在構建新的穩定 C API,將大大改善擴展的維護體驗

DuckDB 中的存儲與加密 引言

大家好,歡迎來到我的演講。今天我將為大家介紹 DuckDB 中的存儲與加密。你可能會好奇為什么要把存儲和加密放在一起講——這是因為要真正理解加密是如何實現的,你至少需要從高層次上了解 DuckDB 的存儲機制是如何工作的。

自我介紹

先介紹一下我自己。我在阿姆斯特丹大學完成了碩士學位,碩士論文是在微軟的一個數據庫團隊(Citus Data)完成的,主題是分布式 PostgreSQL。那是我第一次接觸數據庫內核和計算機科學基礎知識,因為我本科其實并不是計算機科學專業。

但在那之后,我發現自己非常喜歡這個領域。于是我獲得了去 CWI 的機會,在那里從事數據庫與安全交叉領域的研究。最終,這段經歷把我帶到了 DuckDB Labs。目前我是 DuckDB Labs 的軟件工程師,過去一年我為 DuckDB 的加密功能做出了相當多的貢獻。

DuckDB 如何保護你的數據?

首先我想強調的是,DuckDB 保護的是靜態數據(data at rest)。這意味著數據只在寫入磁盤的那一刻才會被加密。

DuckDB 有兩種加密方式:

1. Parquet 加密

Parquet 加密已經存在一段時間了,大約兩年前在 0.10 版本中就已發布。DuckLake 在加密模式下也使用 Parquet 加密,本質上就是寫入加密的 Parquet 文件。

使用方法很簡單:通過 PRAGMA 添加加密密鑰,然后就可以將明文 Parquet 文件復制為加密的 Parquet 文件。

2. 數據庫文件加密

數據庫文件加密不僅加密主數據庫文件,還會加密預寫日志(Write-Ahead Log,WAL)和臨時文件。在本次演講中,我會按照這個順序介紹這三種不同類型的文件。

加密數據庫文件也很簡單:只需在附加數據庫時指定加密密鑰,還可以選擇指定加密算法(如 GCM)。

加密算法

DuckDB 使用高級加密標準 AES。這個加密標準有多種加密模式,DuckDB 目前支持兩種:GCMCTR

今天我不會深入講解這些加密模式的工作原理,但有一點很重要:這兩種都是隨機化加密算法。這意味著即使你使用相同的密鑰,對兩個完全相同的明文進行加密,也會產生不同的密文(前提是實現正確)。這一點很重要——攻擊者查看你的加密數據時,永遠無法推斷出底層數據是否相同。

關于 GCM 模式

GCM 是一種行業標準加密算法,被廣泛應用于各種系統。有幾個要點需要了解:

?Nonce(一次性數字)/ 初始化向量(IV):這是一個唯一的字節序列,DuckDB 在加密每個數據塊之前自行生成。它確保所有數據以隨機化方式加密。?Tag(標簽):GCM 在加密數據塊后會計算一個標簽,本質上類似于校驗和,但具有更強的安全保證。

密鑰管理

當你輸入加密密鑰時,DuckDB 并不會直接使用這個密鑰來加密數據。相反,它會將你的密鑰輸入一個密鑰派生函數(Key Derivation Function)。這個函數還會接收一個隨機的數據庫標識符作為輸入,最終生成一個安全的 32 字節加密密鑰,這個密鑰才是實際用于加密數據的密鑰。

這種設計的好處是:即使你使用相同的密鑰加密多個不同的數據庫文件,實際使用的加密密鑰也是不同的,這是一層額外的安全措施。

重要提示:請永遠不要使用同一個密鑰加密多個不同的文件,這通常被認為是不安全的。

密鑰驗證機制

當你加密數據庫文件時,我們會使用一個小技巧來驗證解密時使用的密鑰是否正確。我們會加密一段已知的明文——在 DuckDB 中這段文本叫做"ducky"——并將其作為元數據存儲在數據庫頭部。當你嘗試讀取加密文件時,我們首先會查找這段元數據并嘗試解密。如果成功,說明密鑰正確;如果失敗,我們會提前終止并報錯。

安全的密鑰緩存

如果密鑰驗證通過,我們會將密鑰存儲在一個安全的加密密鑰緩存中。這個緩存與普通緩存不同:我們精確跟蹤密鑰存儲的位置,并鎖定密鑰所在的內存區域,防止密鑰被意外交換到磁盤。此外,當你不再使用密鑰時,我們會確保密鑰從內存中被完全清除。

DuckDB 存儲結構

要理解加密機制,需要先了解 DuckDB 的存儲結構。

文件頭部

當 DuckDB 寫入文件時,首先會寫入數據庫頭部:一個主頭部和兩個數據庫頭部。

主頭部包含:

?校驗和(檢查頭部是否損壞)?魔數(Magic bytes)?存儲版本?標志位(例如指示文件是否已加密)?數據庫標識符?加密元數據

數據庫頭部包含:

?迭代計數?文件中的塊數量?塊大小?向量大小?序列化兼容性版本

數據存儲

在頭部和元數據之后,DuckDB 以行組(Row Groups)的形式存儲實際數據。這與 Parquet 類似,DuckDB 中一個行組大約包含 12 萬行。行組被分割成列段(Column Segments,內部稱為 Column Data),列段又進一步劃分為(Blocks)。

塊的結構很簡單:

?固定大小為 256 KB?包含一個 8 字節的塊頭部(存儲檢查點信息)?其余空間用于存儲數據

值得注意的是,DuckDB 在存儲數據到塊之前會先嘗試壓縮數據,256 KB 的塊大小對我們使用的壓縮算法來說效率很高。

主數據庫加密

注意:1.4 版本和 1.5 版本的加密結構略有不同,我這里介紹的是即將在大約兩周后發布的 DuckDB 1.5 版本的結構。

頭部加密

DuckDB 不加密主數據庫頭部,原因有二:

1.主頭部不包含敏感數據,攻擊者讀取也無妨2.我們需要讀取其中的加密元數據來確定使用的加密算法、密鑰大小等信息

但是,后續的數據庫頭部以及之后的所有數據都會被加密

塊級加密

我們選擇在塊級別進行加密,主要有三個原因:

1.壓縮優先:我們可以先壓縮數據再加密,減少需要加密的數據量2.大小合適:塊的大小剛好可以容納初始加密開銷3.按需解密:執行查詢時,你很可能不需要讀取整個數據庫文件,這樣可以只解密計算查詢結果所需的那些塊

對于加密的塊,塊頭部從 8 字節變為 40 字節

?前 12 字節:Nonce?接下來 16 字節:Tag?4 字節空白(用于對齊)?8 字節:加密后的校驗和

我們也會加密校驗和,這是一個額外的安全措施,防止攻擊者提前讀取。

預寫日志(WAL)加密

預寫日志是一個追加式文件。當你對數據庫做出更改時,更改會先寫入 WAL,然后才會傳播到主數據庫文件。WAL 主要用于崩潰恢復,也對 ACID 事務(原子性、一致性、隔離性、持久性)很重要,某些數據庫系統還用它來提升性能。

WAL 結構

WAL 的結構如下:

?首先是元數據(WAL 版本)?然后是數據庫標識符(用于確認 WAL 是否屬于當前數據庫文件)?之后按條目存儲每個更改

每個 WAL 條目包含:

?長度前綴(指示需要讀取多少字節)?校驗和(檢查條目是否損壞)?條目內容

WAL 刷新時機

大多數時候你可能不會注意到 WAL 的寫入,因為 WAL 會在特定時間點被刷新:

1.手動觸發檢查點時2.DuckDB 執行自動檢查點時(當 WAL 超過一定大小時)3.正常關閉數據庫時(如果崩潰,WAL 會被保留用于恢復)

WAL 加密方式

對于 WAL 加密:

?元數據保持明文:我們需要確定 WAL 是否已加密?按條目加密:每個條目單獨加密

加密后的條目結構:

?長度(明文,因為需要知道要解密多少字節)?Nonce?加密后的校驗和和條目內容?Tag

臨時文件加密

臨時文件在數據溢出到磁盤時產生,這可能發生在執行需要大型聚合或大型連接的復雜查詢時。

通常 DuckDB 會在查詢執行后自動清理這些文件,但在崩潰情況下它們可能會被遺留。因此我們也需要加密這些文件。臨時文件的結構與塊和 WAL 條目類似,加密方式也相同。

我們在去年 11 月發布了一篇博客文章,如果你想了解更多關于 WAL 加密或臨時文件加密的內容,可以參考那篇文章。

加密 API

正如剛才 Sam 在擴展演講中提到的,DuckDB 不希望有任何外部依賴,但我們確實需要一個proper加密 API。OpenSSL 是理想選擇,但我們不能直接將它鏈接到 DuckDB 核心中。

從 mbedTLS 到 OpenSSL

最初的 Parquet 加密實現使用了一個叫 mbedTLS 的庫,我們精簡后放入了 DuckDB 核心。但問題是 mbedTLS 只依賴純計算,不利用任何硬件指令,導致速度相當慢。

我們需要 OpenSSL。

巧妙的解決方案

我們注意到,使用 DuckDB 的人通常也會使用 HTTPS 擴展,而這個擴展需要 OpenSSL。所以我們做了一個技巧:當你加載 HTTPS 擴展時,我們會用 OpenSSL 的加密 API 覆蓋 mbedTLS 的加密 API。這樣,只要加載了 HTTPS 擴展,你的加密就會獲得硬件加速。

實際上,現在我們在大多數情況下會自動加載 HTTPS 擴展。這是因為寫入加密數據庫需要使用安全的隨機數生成器,而安全的隨機數生成器需要專用的硬件指令支持。因此,我們禁用了 mbedTLS 寫入加密數據庫文件的功能。

好消息是,使用 OpenSSL 時,讀取加密數據幾乎不會有明顯的性能下降,因為它非常快。

總結

本次演講的主要要點:

?DuckDB 能夠通過 Parquet 加密數據庫文件加密來加密靜態數據?加密范圍包括數據庫文件、預寫日志和臨時文件?加密密鑰得到安全管理?加密帶來的性能開銷可以忽略不計

感謝大家!

問答環節要點

Q:加密塊是如何被掃描的?元數據和統計信息存儲在哪里?

A:DuckDB 在存儲實際數據之前會存儲大量元數據,包括指向特定行組統計信息的指針等。基于這些信息,DuckDB 可以跳過大量數據,并且知道需要解密哪些塊。元數據不在塊本身中,而是單獨存儲的。

Q:如果只需要檢索塊中的一行數據,是否需要解密整個塊?

A:理論上如果使用 CTR 模式可以實現隨機訪問,但 DuckDB 目前的實現需要解密整個塊。不過實際上,即使你只需要讀取一行數據,DuckDB 也需要讀取整個塊。

Q:用于驗證密鑰的"ducky"這個詞很短,是否存在碰撞風險?

A:確實存在一定風險,但我們不想占用太多空間,這是一個權衡。未來可能會調整這個設計。

Q:塊頭部中的空白部分是什么用途?

A:有兩個原因。首先,Nonce 的大小理論上可以改變(雖然我們現在固定為 12 字節)。其次,塊頭部設為 40 字節是因為我們需要計算整個塊數據的校驗和,校驗和需要 8 字節對齊,所以用 4 字節的空白來實現正確的對齊。

Q:Nonce 是如何生成的?是隨機生成一次然后遞增嗎?

A:Nonce 由隨機數生成器生成 12 字節的隨機數據。根據加密模式不同,加密 API 會在這 12 字節末尾添加計數器,所以實際的 Nonce 是 16 字節。每加密 16 字節數據,計數器就會遞增。這由加密 API 內部處理。

Q:既然有認證標簽,校驗和還有必要嗎?

A:嚴格來說不是必需的,不做校驗和可以作為一個優化。但我們選擇保留它,寧可安全一些。

Q:數據庫大小會增加多少?

A:對于常規數據庫加密,大小開銷基本可以忽略。WAL 的大小會增加得更多,因為每個條目都需要存儲 Nonce 和 Tag。如果你進行大量快速更新,WAL 可能會顯著增長,但這種情況比較少見。

Q:密鑰管理有什么最佳實踐?比如是否可以使用外部密鑰保管庫?

A:我的建議是:你輸入的密鑰越安全,加密就越安全。我們確實允許使用很短的用戶密鑰,但顯然這會影響最終加密的安全性。大多數用戶會使用 KMS(密鑰管理服務)來管理密鑰。

DuckPL:在 DuckDB 中實現 PL/pgSQL 用戶自定義函數 演講者介紹

大家好,我先簡單介紹一下自己。我從2020年初就開始成為 DuckDB 的長期貢獻者,這要感謝 Hannes——因為他當時不想實現遞歸 CTE。而我今天要講的用戶自定義函數項目,恰恰需要用到遞歸 CTE,所以我最終自己動手實現了它。

在 DuckDB 項目中,當查詢去相關化或優化器的某些地方出現問題時,我通常也會參與修復。在日常工作中,我來自學術界,主要研究方向是查詢優化、執行引擎設計,以及用戶自定義函數——更具體地說,是如何消除它們。今天來介紹這個項目確實有點諷刺。我對編譯器和編程語言也很感興趣,這一點待會兒會變得很重要。

DuckDB 用戶自定義函數的現狀

目前 DuckDB 支持宏(Macro),這是一種簡單的文本替換機制,可以用于簡單的表達式。它們確實很好用,也有很多用戶在使用。但問題是,你無法在其中使用 if 語句——比如當條件為真時執行某些操作,條件為假時執行其他操作。你也無法在里面放入 CREATE TABLE 語句然后返回結果。

我知道你們中的大多數人可能會用 Python 或 R 來定義 UDF,這當然沒問題。但我認為這在某種程度上打破了 DuckDB"單文件、零依賴"的承諾。這正是我想要解決的問題——DuckPL 項目的核心理念就是在 DuckDB 內部提供 PL/SQL 接口。

DuckPL 是什么

我想提供的是讓用戶能夠直接在數據庫系統內部使用用戶自定義函數的能力。舉個簡單的例子,這個函數計算 Collatz 猜想需要多少步才能達到終點。有趣的是,我可以使用 while 循環、if 語句、在代碼中定義變量,當然也可以返回值并調用這個函數。

如果你問我大學里的德國同事,他們會說:"你不需要 UDF,用純 SQL 就行。"對于這個簡單的例子來說確實可以,但當 UDF 變得復雜時,純 SQL 方案就不那么容易實現了。而且如果能在系統內部直接執行這些函數,就不需要任何外部依賴。

讓我演示一下。我這里運行著一個內存數據庫,直接把剛才幻燈片上的 Collatz 函數粘貼進去,函數就注冊到數據庫系統中了。現在我們可以直接調用它——它能工作,計算出了結果。就這么簡單。我可以使用循環、條件判斷,想做什么都可以,而且一切都在系統內部完成。

系統架構

要讓這個演示正常工作,需要幾個關鍵組件。

解析器:我們使用 PostgreSQL 方言,因為 DuckDB 本身就依賴 PostgreSQL 解析器。但 Mark 在2018年左右把 PL/pgSQL 相關的解析代碼從系統中移除了,所以我們需要兩個解析器——一個解析 CREATE FUNCTION 語句,另一個解析 PL/pgSQL 函數體。函數體實際上就是兩個美元符號之間的字符串。目前我們依賴 libpg_query 的解析基礎設施,但 DuckDB 正在遷移到 PEG 解析器,我們也會跟進。

轉換器:我們需要把 PostgreSQL 的抽象語法樹轉換成我們自己的內部表示。如果你看過 PostgreSQL 的代碼(請不要這樣做),你會發現它有五種不同的節點類型來表示循環——整數循環和查詢結果循環用的是不同的結構。我們不這樣做。我們的內部表示是語法無關的,因為我們希望能夠替換前端。目前我們追求 PostgreSQL 兼容性,但將來按照 DuckDB"友好 SQL"的理念,我們會設計自己的語言。

我們的內部語言非常精簡但足夠強大。比如 while 循環,我們不直接表示為 while 循環,而是轉換成一個"永遠循環"加上 break 語句——本質上就是基于 goto 的程序。這樣做簡化了很多工作,也方便未來引入新的前端,比如 PL/Python 或 DuckDB 專用語言。

持久化存儲:我們希望 UDF 是持久化的。但目前擴展 catalog 的鉤子不多,所以我們借鑒了 DuckLake 處理宏的方式——直接把 UDF 定義存在表里。這樣做很簡單,還能享受加密等好處。我們不只存儲用戶提供的 PL/SQL 代碼,還會把函數體序列化成 DuckDB 格式的 blob 存儲,避免每次調用都重新解析。

執行引擎設計

執行方面有一個關鍵點我想詳細說明。目前我們實現的是簡單的樹遍歷解釋器,但我們使用了一個技巧。普通的樹遍歷解釋器會使用 C++ 調用棧來存儲狀態,但這在 DuckDB 中是個問題,因為你無法暫停和恢復執行。特別是對于表值函數,這會在不使用 DuckDB 執行器基礎設施的情況下填滿內存。

所以我們使用顯式棧,在堆上而不是調用棧上管理。這讓我們可以根據執行情況推入新的棧幀。比如執行循環時,我們把循環壓棧,然后繼續執行循環內部;檢查條件時再壓入一個新幀;根據條件結果決定是跳轉到 break 還是繼續執行。

這種設計讓我們能夠實現流式返回。我再演示一個例子:這個 infinite 函數返回一個大整數集合,內部是一個永不終止的循環,不斷遞增并返回值。如果在 PostgreSQL 上運行這個函數,它會永遠執行下去,無法返回任何結果,也無法用 LIMIT 中斷。

但在 DuckPL 中,我們模仿 DuckDB 物理算子的行為:填滿一個數據塊后就把控制權交還給 DuckDB,告訴它"我還有更多輸出"。系統可以決定是否需要更多輸出。這樣我們就能實現提前終止。

SELECT * FROM infinite() LIMIT 10 * 2048;

這條查詢在 DuckDB 的術語中就是讀取10個數據塊,執行完全正常,而不是無限循環。我們還可以組合使用這些函數——比如把 infinitecollatz 結合使用。

表達式求值優化

在 PL 解釋系統中,表達式求值是性能的關鍵。代碼中那些黑框部分都是 SQL 表達式——我們添加了 while 循環等控制流,但表達式仍然是純 SQL。

如果用慢方法,每個表達式都包裝成 SELECT 語句執行。想象一下,如果循環執行一千次迭代,那就是一千個查詢,非常慢。

我們的做法是直接使用表達式執行器。雖然系統并不直接支持這樣做,但我們還是這么做了。簡單來說,我們準備一個查詢如 SELECT x > 1,從語句中提取 x > 1 這個表達式,然后直接用表達式執行器對數據塊執行,而不是跑完整的查詢執行器。

結果相當不錯——對于這類函數,我們快了大約30倍。

當前支持的功能

DuckPL 目前還沒有開源,你們還用不了。但我們已經支持了相當多的功能:

?標量函數和表值函數?變量和賦值?所有數據類型,包括用戶自定義類型?復合類型,如表類型(比如 TPC-H 的 lineitem)?控制流方面已經功能完整:if、所有類型的循環、break、continue、return 和 return next?支持帶簡單操作的游標(fetch into 變量),但還不支持高級游標操作如滾動、跳轉?支持 printf 風格的調試(使用 RAISE)

不支持或暫不支持的功能

?動態 SQL:DuckDB 已經有 query() 函數可以輸入字符串得到結果,所以我們不需要重復實現?高級游標功能:暫未規劃,看社區反饋?觸發器:因為 DuckDB 本身不支持觸發器

未來規劃

?支持注冊為聚合函數和窗口函數?異常處理(try-catch 語義)?事務支持(目前會產生嵌套連接問題)?UDF 優化器?編譯到純 SQL:很多 UDF 其實可以用 WITH RECURSIVE 等純 SQL 表達,這樣就能充分利用 DuckDB 執行引擎的性能

未來愿景

PostgreSQL 只允許你定義函數并在查詢中調用。我認為在 DuckDB CLI 中提供類似 REPL 的體驗會是很好的補充。比如用 LET 語句定義變量,直接在 CLI 中寫循環、打印輸出,用 DuckDB CLI 替代 Python CLI。

我們還會遷移到 PEG 解析器基礎設施,利用我們在 UDF 編譯方面的研究成果,逐步把這個想法產品化。

總結

我們的路線圖是:

1.PostgreSQL 兼容性優先:大量現有代碼庫可以幾乎無縫從 PostgreSQL 遷移到 DuckDB,沒有學習曲線,而且 LLM 也能生成這些代碼2.智能執行:在兼容性基礎上追求速度3.混合執行和 CLI 功能:最終目標

問答環節

問:執行引擎是否應用了向量化?

目前還沒有,現在是逐行執行。我們當然想改進,但這還是第一個版本,連 alpha 都算不上。

問:能否從內部表示反編譯回源代碼?

我們不需要,因為我們存儲了用戶的原始輸入。

問:有沒有考慮用 V8 或 JIT 編譯來解決解釋器的性能瓶頸?

我對這個做過大量研究。瓶頸不在于解釋本身,而在于命令式執行和聲明式 SQL 執行之間的阻抗不匹配。這個問題用 JIT 解決不了。

Gizmo Edge:基于 DuckDB 的分布式物聯網邊緣分析引擎 演講者介紹

大家好,我是來自 Gizmo Data 的 Philip Moore。今天我要介紹的是 Gizmo Edge,這是一個為物聯網設計的預覽版分布式引擎,用于在邊緣執行分析任務。它基于 DuckDB 構建,我非常高興能來到這里與大家交流。

簡單介紹一下我自己:我是一個數據狂熱者和構建者,從事數據相關工作已經超過25年。職業生涯的大部分時間我都在使用 Oracle,后來轉向開源技術,并立刻愛上了 DuckDB——它是一個出色的嵌入式引擎,速度極快,具備我們都喜愛的所有優點。

我曾是美國海軍陸戰隊員,那是很多年、很多磅、很多頭發以前的事了。我對 DuckDB 有過一些小貢獻,比如構建了 struct_insert 函數讓你可以修改結構體,引入了 hugeintbit_count 等功能。我還曾經請求過加密功能,看到它最終實現真的很棒。

為什么要創建 Gizmo Edge

我創建 Gizmo Edge 是因為想要一個能夠在邊緣執行分析的引擎。DuckDB 和 SQLite 的嵌入式特性首次使這成為可能。實際上我最初是用 SQLite 開始構建的,待會兒會解釋為什么轉向了 DuckDB。

物聯網領域面臨幾個核心挑戰:

數據量持續增長:物聯網傳感器、移動設備、邊緣節點產生的數據量巨大,增長速度遠超集中化處理的能力。

數據傳輸成本高昂:從云端下載數據到設備的出口流量費用非常昂貴。

延遲問題嚴重:通常需要等待數據被攝入云存儲,可能需要數小時甚至數天才能讀取和聚合數據。

Gizmo Edge 是一個分布式引擎,讓你可以在邊緣設備上使用 DuckDB,實現分治策略處理分析工作負載,或者從邊緣設備拉取數據進行聚合。

創建的初衷

讓我創建這個項目的直接原因是:我當時在 Kroger 工作,我們有數十億行交易數據,花費數百萬美元在 Oracle Exadata 這樣的技術上來處理。即使這樣,運行一個查詢仍然需要等待五分鐘。這讓我非常沮喪——為什么我們不能把數據分發到一千個工作節點上,讓每個節點獨立處理各自的數據塊呢?

我到處尋找能做到這一點的技術,包括 Spark,但都不太理想。所以我決定自己創建,而 DuckDB 讓這成為可能。

我對異構工作節點特別著迷。想想典型的 Spark 集群、Databricks 集群或 Snowflake,所有工作節點都是統一的——相同的機器、相同的存儲特性、相同的 CPU、相同的內存。我想要的是一個由各種不同設備組成的工作節點集群。

當然,核心是 DuckDB 驅動。另外,Apache Arrow 對我來說也非常重要——我之前在 Voltron Data 工作時引入了 Apache Arrow,它真正革新了數據傳輸方式。Arrow 可以發送高度壓縮的列式數據,傳輸效率高,而且是零拷貝的,不需要反復序列化和反序列化。這讓數據從邊緣設備傳輸到協調器變得更加流暢。

架構概述

Gizmo Edge 的架構是這樣的:中間有一個集中式協調器,終端用戶向協調器發送 SQL 查詢,協調器將工作分發到各個工作節點。這些工作節點可以是異構的——可以是 iPhone(聽起來很瘋狂)、筆記本電腦、MacBook、臺式機、Kubernetes 節點、Linux 服務器,甚至是物聯網設備。由于 DuckDB 的嵌入式特性,它幾乎可以在任何設備上運行。

服務器/協調器的職責是:解析 SQL,檢測聚合函數,決定是分發查詢還是在服務器端本地運行(比如簡單的 SELECT *)。它將工作分發給工作節點,并聚合最終結果。

工作節點的職責是:下載各自的數據分片,使用 DuckDB 本地執行查詢,通過 WebSocket 以 Arrow IPC 格式返回結果。它們可以運行在 Kubernetes、Linux、macOS、iOS、Windows 等任何平臺上。

客戶端是一個交互式 SQL REPL,帶有基于 Web 的 SQL 導航器。你可以開啟或關閉分布式模式,并接收服務器返回的結果。

整個數據傳輸都使用 Arrow 格式。

查詢執行流程

當你發出查詢時,流程是這樣的:

1.工作節點首先向服務器認證,請求獲取數據分片2.服務器驗證后發送數據分片,保留 MD5 哈希,同時分享 SHA-256 哈希給工作節點3.工作節點解壓數據,驗證 SHA 哈希匹配,然后計算 MD5 哈希發回服務器4.服務器確認工作節點確實處理了數據,建立信任5.查詢到來時,服務器解析并決定是否分發6.工作節點執行查詢,以 Arrow 格式返回結果7.服務器聚合結果并發送給客戶端

如果需要額外安全性,還可以啟用 mTLS。

DuckDB 的使用方式

每個工作節點都運行 DuckDB。它們接收一個 Zstandard 壓縮的數據分片,解壓后從 Parquet 文件創建 DuckDB 數據庫。執行完成后,通過 Arrow 格式將結果發回服務器。

服務器端使用 PyArrow 進行零拷貝的表連接,然后執行匯總查詢,按分組鍵進一步聚合所有工作節點的結果。

查詢轉換

用戶發出的查詢不一定是直接分發給工作節點的查詢。比如平均值(AVG)——你不能對平均值再求平均值,那樣會得到錯誤結果。

假設用戶查詢:

SELECT AVG(quantity), AVG(extended_price) FROM ...

實際分發給工作節點的是:

SELECT SUM(quantity), COUNT(quantity), SUM(extended_price), COUNT(extended_price) FROM ...

收回結果后,服務器計算 SUM(sum) / SUM(count) 得到正確的平均值。

服務器必須解析查詢,理解聚合函數和分組鍵,然后進行相應轉換。

分片管理

目前 Gizmo Edge 還是原型階段,分片是預先構建的。理想情況下,工作節點應該能夠動態查詢云存儲中的 Parquet 文件塊。在演示中,我使用的是 TPC-H 100GB 數據集(相比 10TB 來說很小)。

分片存儲在云存儲中,服務器維護一個分片清單。當工作節點簽入時,服務器根據分發情況決定分配哪個分片。

定向廣播(Targeted Broadcast)

對于分析用例,我開發了一種叫"定向廣播"的技術。它特別適合星型模式——有一個中心事實表和周圍的維度表。

工作原理是:

1.首先獲取事實表的一個哈希分區塊2.然后過濾維度表,只保留支持該分片中事實數據所需的記錄

這樣每個工作節點就擁有一個微型星型模式、微型數據倉庫。這帶來很多好處:

?內連接是無損的?連接操作完全卸載到工作節點?服務器不需要做任何連接?工作節點之間不需要相互通信?工作節點可以獨立完成連接、過濾、聚合、分組和排序

未來我們計劃使用 DuckDB 的布隆過濾器功能,雖然可能有一些誤報,但會在連接時被丟棄,這將大大加速分片生成過程。

技術棧

預覽版是用 Python 寫的(我知道這總是引來笑聲),如果是生產版本可能會用 C++ 或 Rust。我們使用 DuckDB 最新版本,用 PostgreSQL 解析器提取 SQL 標記來確定分組鍵、聚合函數、排序和限制等。數據序列化使用 Apache Arrow IPC,網絡通信使用 WebSocket 實現低延遲連接。

部署方式

可以在本地筆記本上運行,可以部署到 Kubernetes,也可以在各種邊緣設備上運行。我的演示使用 Azure Kubernetes Service 集群。

為什么 DuckDB 是完美選擇

?嵌入式零依賴:不需要安裝一堆庫,易于部署到邊緣設備?我的轉型故事:最初用 SQLite 構建時,我和 SQLite 的創始人 Richard Hipp 交流,他告訴我 DuckDB——一個像 SQLite 一樣自包含但專為 OLAP 優化、速度極快的分析引擎。然后我聯系了 Hannes,很早就開始使用 DuckDB?跨平臺運行:我們用 DuckDB 的 TPC-H 生成器構建分片?全面使用 Arrow:數據傳輸統一使用 Arrow 格式?豐富的 SQL 支持:不過由于分布式和無共享架構的特性,窗口函數等功能還不支持

現場演示

讓我打開瀏覽器連接到 Gizmo Edge。這是一個 SQL IDE 界面,有一個小型模式瀏覽器,可以看到 TPC-H 模式。

運行一個查詢——你可以看到它分發到了 98 個運行在 Azure Kubernetes 上的 Linux 工作節點,還有一個 macOS 工作節點。那個 macOS 工作節點在哪里?就是這臺 MacBook。

清除日志,再次執行。你可以看到工作節點上有活動——它收到了查詢。用戶請求的是平均值,實際發送給工作節點的是求和和計數。工作節點執行查詢(在 iOS 和 macOS 上會導出為 Parquet),耗時不到 0.05 秒,因為它只有大約 1GB 的數據。然后通過 WebSocket 發送 Base64 編碼的 Parquet 數據。服務器還會給反饋:"你是最快的"或者"你不是最快的工作節點,換份工作吧"。

現在來點更刺激的——我要拿出我的 iPhone。

(連接 iPhone 到 Gizmo Edge 服務器)

再運行一個查詢——成功了!iOS 工作節點、macOS 工作節點,加上 98 個 Linux 工作節點,總共 100 個工作節點。它們各自處理自己的數據塊,以 Arrow 或 Parquet 格式返回結果,服務器進行最終聚合。

有些查詢不適合分發,比如沒有聚合的 SELECT——你不想讓一堆工作節點往服務器發送數百萬行數據。解析器會檢測這種情況,讓服務器本地執行。

有趣的是,iPhone 居然比我的 MacBook 還快,它們處理的數據量相同。我喜歡看它們競速。

萬億行挑戰

現在切換到深色模式,來點真正刺激的。

這個數據集有一個叫 measurements 的表。讓我先看看:

SELECT * FROM measurements;

這不會分發,因為是 SELECT *。表結構很簡單,只有 station 和 measure 兩列。讓我們看看有多少行:

SELECT COUNT(*) FROM measurements;

一萬億行記錄!

有人做過萬億行聚合嗎?數據量非常大。我參加了 Coiled 公司的萬億行挑戰,想看看 Gizmo Edge 能否完成。

查詢很簡單:

ORDER BY station;

沒有 WHERE 子句,必須掃描所有數據,不能作弊。

讓我們運行它——我們把查詢分發到了 一千個工作節點。它們正在處理... 完成了!

一萬億行記錄,幾秒鐘完成!

(掌聲)

每個工作節點大約有 10 億行數據。我們還可以加一些計算:

GROUP BY station;

可以看到有 412 行結果,每行代表約 250 億條記錄被聚合成一個值。

當然也可以加過濾條件:

SELECT ... WHERE station = 'ABHA'

瞬間完成!DuckDB 不需要索引。工作節點找到目標行后,返回更小的結果集給服務器。

未來計劃

這仍是原型階段,用 Python 寫的,但已經非常快了。如果用 Rust 或 C++ 重寫會更好。我們的計劃包括:

?更智能的查詢規劃?動態工作節點發現和自動注冊?自動擴縮容?利用 DuckDB 擴展生態系統?生產級加固和安全最佳實踐

問答環節

問:分片具體如何工作?如果我有 S3 上的數據集,如何分發到工作節點?

目前是手動過程。你需要知道整體數據集大小和想要多少分片。比如我有一千個工作節點,一萬億行,就除以一千,每個分片大約 10 億行、2GB 左右。理想情況下應該能動態分片——如果啟動一千個工作節點,它們應該知道各自獲取千分之一的數據。更進一步,應該考慮設備能力:iPhone 可能只能處理 1GB,而 64 核的 Kubernetes 節點可以處理幾十億行。

問:非可加性聚合函數如何處理?比如 COUNT DISTINCT?還有連接策略?

COUNT DISTINCT 是個很好的問題,在零售領域尤其常見——你想知道有多少獨立顧客購買了某類產品。

有幾種方法:

1.近似方法:使用 HyperLogLog 草圖。Rusty 構建了一個草圖擴展,可以在工作節點構建草圖,發送到服務器聚合,得到約 99% 準確的 NDV 值2.精確方法:如果基數較低(百萬級以下),可以使用位圖,每個不同值對應一個位位置,然后位或聚合所有位圖,得到 100% 準確的結果

中位數可能比較棘手,但也有近似計算方法。這些功能還沒有全部實現,但 DuckDB 生態系統有很多工具可用。

關于連接:內連接工作得很好。DuckDB 自己決定使用哈希連接還是嵌套循環連接。但左外連接目前不支持,因為工作節點只有支持其事實數據的定向維度集,處理外連接需要更高級的架構。

如果想了解更多,請訪問 gizmodata.com 查看 Gizmo Edge。代碼倉庫目前還不公開,但可能有一天會開源。另外也請關注 Gizmo SQL,這是一個用 C++ 寫的項目,讓你可以在本地或云端把 DuckDB 作為服務器運行。

謝謝大家!

老馮點評

熟悉老馮的人都知道,老馮最愛的數據庫是 PostgreSQL,而要說第二喜歡的數據庫,當屬 DuckDB。

我之前寫過幾篇文章,提出過一個觀點: 世界。原因很簡單:DuckDB 正在變成“分析能力的通用部件”——它不是要替代一切,而是特別適合被集成、被嵌入、被當作加速器或計算單元。

DuckDB 和 PostgreSQL 的相似度也確實高得離譜,至少體現在兩點上:

第一,它的可擴展性在主流數據庫里幾乎僅次于 PG:擴展機制成熟,生態繁榮,而且正在從“不穩定 C++ API”向“穩定 C API”過渡,這一步如果走順,會顯著降低生態維護成本,進一步加速擴展爆發。

第二,它高度以 PG 語法為基礎做增量改進:你能感受到 DuckDB 的設計哲學不是“推倒重來”,而是“站在 PG 語法與用戶習慣上,把分析體驗推到極致”。這次 DuckPL 直接以 PL/pgSQL 為藍本,更是把“PG 兼容”從 SQL 表層推進到“數據庫內編程模型”這一層。說得直白點:DuckDB 不是在蹭 PG,它是在主動把自己納入廣義 PG 生態,換取開發者心智與遷移成本優勢。

也正因此,PG 世界對 DuckDB 的接納度非常高,甚至可以說幾年前就開始了“”:把 DuckDB 作為 OLAP 引擎/加速器,嵌進 Postgres 發行版、托管服務、數倉產品、混合架構里。現在你能看到的典型選手游:


這場比賽的看點從來不只是“誰把擴展裝上了”,而是誰能把工程邊界、查詢語義、數據同步、權限/安全、運維體驗做成一套可長期使用的產品級方案。縫合不難,縫合得優雅才難。

作為對照,最近也能看到另一條有意思的路線:把 DuckDB 縫進 MySQL 體系(阿里云的 ALISQL)。這件事從工程角度當然值得尊重:能在既有體系里引入更強的分析能力,說明團隊有沉淀,也愿意啃硬骨頭。


老實說,我覺得挺有意思的,阿里對于 MySQL 的執念似乎非常深。要給 MySQL 的兄弟謀出路,繼續給 MYSQL 續命,這種想法老馮也可以理解,但很明顯:就算你給 DuckDB 打錢贊助,人家也不會在原則問題上妥協 —— 他們做了 MySQL 語法的兼容修改,想要提交給 DuckDB 上游,被拒絕了。

因為這里的基本現實就是 了。這一點從資本市場,以及所有云廠商的技術布局都可以明顯看出來。強行為一個即將死亡的技術續命,雖然有一種悲壯的美感,但并沒有什么用。老馮覺得阿里云數據庫技術團隊在做 MySQL 上還是有沉淀的,也是有情懷的技術人。所以老馮不會嘲笑、揶揄他們 —— 這只是技術方向上的問題,我還是希望他們能走出一條自己的道路。

再把鏡頭拉遠一點:,其實已經開局了。Agent 會把“數據讀寫、語義理解、工具調用、反饋迭代”壓成一個閉環,而數據庫就是這個閉環里最硬的地基之一:性能、可靠性、權限、安全、可觀測、可擴展,一個都繞不過去。在這場比賽里,我認為 :生態、可擴展性、工程成熟度、以及越來越強的“作為平臺”的屬性,都是它的不可動搖的護城河。

但如果你問我:有沒有誰有那么一絲機會從 PG 的碗里搶飯?我會點名兩個嵌入式數據庫:SQLite 和 DuckDB。

它們占據了一個非常微妙的生態位:離應用更近、分發更輕、嵌入更自然,特別適合成為 Agent 世界里的“本地事實庫/本地分析引擎/邊緣計算單元”。這類位置一旦卡住,影響力往往不是靠“替代 PG”獲得的,而是靠“繞開傳統數據庫交付路徑”獲得的——這才是它們真正危險(也真正迷人)的地方。我認為,他們也會在自己的細分領域里大放光彩。

特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關推薦
熱點推薦
直降3519元!新iPhone 又降價了,這次真的離譜啊

直降3519元!新iPhone 又降價了,這次真的離譜啊

科技堡壘
2026-03-31 10:56:16
劉亦菲泳裝照,這豐腴身材誰頂得住美美噠,美到家?

劉亦菲泳裝照,這豐腴身材誰頂得住美美噠,美到家?

娛樂領航家
2026-04-01 23:30:03
公安部:“平安原野—2025”專項行動偵辦危害鳥類案件3562起

公安部:“平安原野—2025”專項行動偵辦危害鳥類案件3562起

極目新聞
2026-04-01 10:18:32
罰200元記3分!這些粵S車主,統統被曝光!

罰200元記3分!這些粵S車主,統統被曝光!

品牌東莞
2026-04-01 11:04:51
游客同里古鎮景區拍照遭商家驅趕搶奪手機,當地:對涉事商戶停業整改

游客同里古鎮景區拍照遭商家驅趕搶奪手機,當地:對涉事商戶停業整改

都市快報橙柿互動
2026-04-01 10:59:51
剛天亮!伊朗突然松口,條件就一個,太現實了

剛天亮!伊朗突然松口,條件就一個,太現實了

林子說事
2026-04-01 13:01:11
馬斯克大膽預言,第三次世界大戰,中俄伊將聯手終結美西方統治

馬斯克大膽預言,第三次世界大戰,中俄伊將聯手終結美西方統治

老斉科普君
2026-04-02 02:05:29
美國要變天了!一個比特朗普更難纏的80后,已經掌握了共和黨

美國要變天了!一個比特朗普更難纏的80后,已經掌握了共和黨

趙探長TALK
2026-04-01 09:30:50
比亞迪要暴雷了?2025年年報公布,凈利潤326億研發投入卻有634億

比亞迪要暴雷了?2025年年報公布,凈利潤326億研發投入卻有634億

瞰瞰數碼
2026-03-31 11:19:19
“余生好好走”,知名央視主持人王小丫,病床上的留言字字催淚

“余生好好走”,知名央視主持人王小丫,病床上的留言字字催淚

近史談
2026-03-31 18:57:49
高考大局已定:若不出意外,2026年高考錄取將迎5大變化!了解下

高考大局已定:若不出意外,2026年高考錄取將迎5大變化!了解下

小談食刻美食
2026-04-01 08:09:17
改寫歷史,真主黨打進了以色列本土

改寫歷史,真主黨打進了以色列本土

星火聊天下
2026-03-30 16:09:46
范冰冰韓國整容歸來,13萬差評成內娛最后報復

范冰冰韓國整容歸來,13萬差評成內娛最后報復

何蕥室內設計
2026-03-31 21:47:55
為什么秦嵐的身材不協調 胸很大 腰很細 臀部很大 身材有點像芭比娃娃

為什么秦嵐的身材不協調 胸很大 腰很細 臀部很大 身材有點像芭比娃娃

手工制作阿殲
2026-04-01 14:16:49
西班牙強調美以無權決定世界規則

西班牙強調美以無權決定世界規則

每日經濟新聞
2026-04-01 07:27:42
“進口”保健品“澳洲優思益”實為國內生產,廣東多部門展開調查

“進口”保健品“澳洲優思益”實為國內生產,廣東多部門展開調查

新京報
2026-04-01 15:03:17
1-4!中國男足慘敗法國淪為墊底 日本0-0 最新排名:歐洲2隊包攬

1-4!中國男足慘敗法國淪為墊底 日本0-0 最新排名:歐洲2隊包攬

越嶺尋蹤
2026-04-01 03:38:12
張雪的故事,可能沒那么燃

張雪的故事,可能沒那么燃

雷斯林
2026-04-01 18:03:20
丹麥華裔王妃文雅麗回香港娘家,還帶上27歲大兒子,母子倆長得像

丹麥華裔王妃文雅麗回香港娘家,還帶上27歲大兒子,母子倆長得像

健身狂人
2026-04-01 17:56:50
天崩開局!2026年畢業生數量1270萬,又到一年最難就業季

天崩開局!2026年畢業生數量1270萬,又到一年最難就業季

菊長秘書
2026-03-30 11:38:56
2026-04-02 04:47:00
老馮云數 incentive-icons
老馮云數
數據庫老司機,云計算泥石流,PostgreSQL大法師
146文章數 55關注度
往期回顧 全部

科技要聞

甲骨文血洗3萬人,47人團隊僅留3人

頭條要聞

特朗普計劃奪取伊朗濃縮鈾:空運挖掘設備 修建飛機跑道

頭條要聞

特朗普計劃奪取伊朗濃縮鈾:空運挖掘設備 修建飛機跑道

體育要聞

NBA擴軍,和籃球無關?

娛樂要聞

張婉婷已決定離婚 找律師討論婚變事宜

財經要聞

電商售械三水光針 機構倒貨or假貨猖獗?

汽車要聞

三電可靠 用料下本 百萬公里的蔚來ES6 拆開看

態度原創

教育
藝術
時尚
房產
軍事航空

教育要聞

省政府:對就業質量不好的專業,落實紅黃牌提示制度

藝術要聞

太壕了!為了一場演唱會,BIG給拉丁天后夏奇拉建5萬人臨時場館

襯衫當外套,好時髦

房產要聞

產業、教育、地產…重大信號發出! 官方定調海口未來5年!

軍事要聞

特朗普:將很快撤出伊朗戰事

無障礙瀏覽 進入關懷版