搜尋
首頁web前端js教程處理分散式系統中的分割資料:深入探討連線、廣播和查詢最佳化

Handling Sharded Data in Distributed Systems: A Deep Dive into Joins, Broadcasts, and Query Optimization

在現代分散式資料庫中,水平擴展資料的需求導致了分片的廣泛採用。雖然分片有助於管理跨多個節點的大型資料集,但它也帶來了挑戰,特別是在執行連接並確保高效的資料檢索時。在本文中,我們探討了應對這些挑戰的各種概念和技術,特別關注廣播連接分片鍵對齊分散式查詢引擎,例如PrestoBigQuery。此外,我們也示範如何使用 Node.jsExpress.

在實際應用程式中處理這些問題

Node.js 與 Express.js 中的分片範例

以下是如何使用 Node.js 和 Express.js 在 PostgreSQL 中實作分片。

PostgreSQL 分片範例

使用 Citus 或使用 Node.js 進行手動邏輯分片:

邏輯分片範例

  1. 分片設定表:
    使用分片表(shard1 上的 user_data 和 shard2 上的 user_data)。

  2. 建立 Express.js API:
    基於分片鍵(例如 user_id)分發查詢。

   const express = require('express');
   const { Pool } = require('pg');

   const poolShard1 = new Pool({ connectionString: 'postgresql://localhost/shard1' });
   const poolShard2 = new Pool({ connectionString: 'postgresql://localhost/shard2' });

   const app = express();
   app.use(express.json());

   const getShardPool = (userId) => (userId % 2 === 0 ? poolShard1 : poolShard2);

   app.post('/user', async (req, res) => {
       const { userId, data } = req.body;
       const pool = getShardPool(userId);
       try {
           await pool.query('INSERT INTO user_data (user_id, data) VALUES (, )', [userId, data]);
           res.status(200).send('User added successfully');
       } catch (err) {
           console.error(err);
           res.status(500).send('Error inserting user');
       }
   });

   app.get('/user/:userId', async (req, res) => {
       const userId = parseInt(req.params.userId, 10);
       const pool = getShardPool(userId);
       try {
           const result = await pool.query('SELECT * FROM user_data WHERE user_id = ', [userId]);
           res.status(200).json(result.rows);
       } catch (err) {
           console.error(err);
           res.status(500).send('Error retrieving user');
       }
   });

   app.listen(3000, () => console.log('Server running on port 3000'));

1. 分散式資料庫中的分片

分片是跨多個資料庫執行個體或分片水平分區資料的過程,以提高效能、可擴展性和可用性。當單一資料庫執行個體無法處理大量資料或流量時,通常需要分片。

分片策略

  • 基於範圍的分片:資料根據鍵的範圍分佈在分片上,例如,按 order_date 對訂單進行分區。
  • 基於雜湊的分片:透過分片鍵(例如 user_id)對資料進行雜湊處理,以將資料均勻分佈在各個分片上。
  • 以目錄為基礎的分片:中央目錄追蹤資料駐留在系統中的位置。

但是,當相關表在不同鍵上分片時,或當一個表需要跨多個分片與另一個表進行聯接時,由於需要分散-聚集 操作,性能可能會下降。這就是理解廣播連接和分片鍵對齊變得至關重要的地方。


2. 分片系統中連接的挑戰

當資料駐留在不同的分片中時,在這些分片之間執行連接可能會很複雜。以下是常見挑戰的細分:

1. 分片鍵錯位

在許多系統中,表在不同的鍵上進行分片。例如:

  • users 表格可能會按 user_id 進行分片。
  • 訂單表格可能會按區域分片。

執行連線時(例如,orders.user_id = users.user_id),系統需要從多個分片中取得數據,因為相關記錄可能不在同一個分片中。

2. 分散-聚集連結

在分散-聚集連結中,系統必須:

  • 向所有保存相關資料的分片發送請求。
  • 跨分片的聚合結果。 這會顯著降低效能,尤其是當資料分佈在許多分片上時。

3. 廣播加入

廣播連線 當被連接的一個表格夠小,可以廣播到所有分片時,就會發生。在這種情況下:

  • 小表(例如使用者)在較大的分片表(例如訂單)所在的所有節點上複製。
  • 每個節點都可以將其本地資料與廣播資料連接起來,從而避免跨分片通訊。

3. 使用分散式查詢引擎進行分片資料

分散式查詢引擎,例如 PrestoBigQuery 旨在跨分散式系統高效處理分片資料和聯結查詢。

急板/Trino

Presto 是一個分散式 SQL 查詢引擎,旨在跨異質資料來源(例如關聯式資料庫、NoSQL 資料庫、資料湖)查詢大型資料集。 Presto 跨分散式資料來源執行聯接,並且可以透過最小化節點之間的資料移動來最佳化查詢。

範例用例:使用 Presto 連線分片資料

orders 依區域分片且 users 按 user_id 分片的場景中,Presto 可以使用其分散式執行模型跨不同分片執行連線。

查詢:

   const express = require('express');
   const { Pool } = require('pg');

   const poolShard1 = new Pool({ connectionString: 'postgresql://localhost/shard1' });
   const poolShard2 = new Pool({ connectionString: 'postgresql://localhost/shard2' });

   const app = express();
   app.use(express.json());

   const getShardPool = (userId) => (userId % 2 === 0 ? poolShard1 : poolShard2);

   app.post('/user', async (req, res) => {
       const { userId, data } = req.body;
       const pool = getShardPool(userId);
       try {
           await pool.query('INSERT INTO user_data (user_id, data) VALUES (, )', [userId, data]);
           res.status(200).send('User added successfully');
       } catch (err) {
           console.error(err);
           res.status(500).send('Error inserting user');
       }
   });

   app.get('/user/:userId', async (req, res) => {
       const userId = parseInt(req.params.userId, 10);
       const pool = getShardPool(userId);
       try {
           const result = await pool.query('SELECT * FROM user_data WHERE user_id = ', [userId]);
           res.status(200).json(result.rows);
       } catch (err) {
           console.error(err);
           res.status(500).send('Error retrieving user');
       }
   });

   app.listen(3000, () => console.log('Server running on port 3000'));

急速將:

  1. 使用分散-聚集取得相關使用者記錄。
  2. 跨節點連接資料。

Google BigQuery

BigQuery 是一個完全託管的無伺服器資料倉儲,擅長執行大規模分析查詢。雖然 BigQuery 抽象化了分片的細節,但它會自動在多個節點之間分區和分佈資料以最佳化查詢。它可以輕鬆處理大型資料集,對於資料按時間或其他維度分區的分析查詢特別有效。

範例用例:在 BigQuery 中加入分片表
   const express = require('express');
   const { Pool } = require('pg');

   const poolShard1 = new Pool({ connectionString: 'postgresql://localhost/shard1' });
   const poolShard2 = new Pool({ connectionString: 'postgresql://localhost/shard2' });

   const app = express();
   app.use(express.json());

   const getShardPool = (userId) => (userId % 2 === 0 ? poolShard1 : poolShard2);

   app.post('/user', async (req, res) => {
       const { userId, data } = req.body;
       const pool = getShardPool(userId);
       try {
           await pool.query('INSERT INTO user_data (user_id, data) VALUES (, )', [userId, data]);
           res.status(200).send('User added successfully');
       } catch (err) {
           console.error(err);
           res.status(500).send('Error inserting user');
       }
   });

   app.get('/user/:userId', async (req, res) => {
       const userId = parseInt(req.params.userId, 10);
       const pool = getShardPool(userId);
       try {
           const result = await pool.query('SELECT * FROM user_data WHERE user_id = ', [userId]);
           res.status(200).json(result.rows);
       } catch (err) {
           console.error(err);
           res.status(500).send('Error retrieving user');
       }
   });

   app.listen(3000, () => console.log('Server running on port 3000'));

BigQuery 自動處理分區和分配,最大限度地減少手動分片的需要。


4. 處理 Node.js 應用程式中的分片鍵錯位

在 Node.js 應用程式中處理分片資料時,經常會出現 分片鍵未對齊 以及需要 分散-聚集 連接等問題。以下是如何使用 Node.jsExpress 來應對這些挑戰。

在 Node.js 中處理廣播連線

如果連接需要在所有分片上廣播一個小表(例如用戶),您可以透過獲取一次小表並使用它與分片表中的資料連接來在應用程式層實現連接。

SELECT o.order_id, u.user_name
FROM orders o
JOIN users u
ON o.user_id = u.user_id;

在 Node.js 中處理分散-聚集查詢

對於涉及分散-聚集連接的查詢(例如,當分片鍵未對齊時),您將需要查詢所有分片並在應用程式層聚合結果。

SELECT o.order_id, u.user_name
FROM `project.dataset.orders` o
JOIN `project.dataset.users` u
ON o.user_id = u.user_id
WHERE o.order_date BETWEEN '2024-01-01' AND '2024-12-31';

5. 分片資料查詢最佳化的最佳實務

處理分片資料和執行連線時,請考慮以下最佳實務:

  1. 對齊分片鍵:如果可能,請確保相關表使用相同的分片鍵。這最大限度地減少了跨分片連接的需求並提高了效能。

  2. 反規範化:在頻繁連接的場景中,請考慮對資料進行反規範化。例如,您可以將使用者資訊直接儲存在 posts 表中,從而減少聯結的需要。

  3. 對小表使用廣播連接:如果其中一個表足夠小,則將其廣播到所有節點以避免分散-聚集查詢。

  4. 預先連接數據:對於經常存取的數據,考慮預先連接並將結果儲存在物化視圖或快取中。

  5. 利用分散式查詢引擎:對於複雜的分析查詢,請使用PrestoBigQuery 等自動處理分散式聯接和最佳化的系統。


6. 使用分片資料進行基於遊標的分頁的最佳實踐

在具有此類分片的分散式系統中,基於遊標的分頁需要謹慎處理,特別是因為資料分佈在多個分片中。關鍵是:

  1. 拆分查詢:獨立查詢每個分片以取得相關資料。
  2. 分頁處理:決定如何對分片資料(貼文或使用者)進行分頁,並收集相關結果。
  3. 在應用程式層級加入:從每個分片中取得結果,在記憶體中加入數據,然後套用下一頁的遊標邏輯。

讓我們來看看如何使用Node.jsExpress 來實現這一點,考慮到資料駐留在不同的分片上並且需要在應用程式層級進行提取後連接。

如何處理分頁和與分片表的連接

假設我們有:

  • 貼文按user_id分片的表格。
  • users 按 user_id 分片的表。

我們想要檢索給定用戶的分頁帖子,但由於用戶和帖子位於不同的分片上,因此我們需要拆分查詢、處理分頁,然後在應用程式層級執行聯接。

方法:

  1. 查詢相關分片:

    • 首先,您需要跨分片查詢 posts 表以取得貼文。
    • 取得相關貼文後,使用貼文中的 user_id 查詢使用者表(同樣是跨分片)。
  2. 分頁策略:

    • 貼文分頁:您可以使用created_at、post_id或其他唯一欄位對貼文表進行分頁。
    • 使用者分頁:您可能需要單獨取得使用者資料或使用 user_id 作為遊標來對使用者進行分頁。
  3. 應用程式層級連線:

    • 從相關分片(貼文和使用者)檢索資料後,在應用程式層級加入它們。
  4. 處理遊標:

    • 取得第一頁後,使用最後的created_at或post_id(來自貼文)作為下一個查詢的遊標。

實施範例

1. 跨分片查詢帖子

在這裡,我們將跨不同的貼文分片執行查詢,並透過遊標(例如,created_at 或 post_id)進行篩選。

2.使用Post資料跨分片查詢用戶

一旦我們從第一個查詢中獲得了相關的 post_id 和 user_id,我們將從相關分片中獲取使用者資料。

   const express = require('express');
   const { Pool } = require('pg');

   const poolShard1 = new Pool({ connectionString: 'postgresql://localhost/shard1' });
   const poolShard2 = new Pool({ connectionString: 'postgresql://localhost/shard2' });

   const app = express();
   app.use(express.json());

   const getShardPool = (userId) => (userId % 2 === 0 ? poolShard1 : poolShard2);

   app.post('/user', async (req, res) => {
       const { userId, data } = req.body;
       const pool = getShardPool(userId);
       try {
           await pool.query('INSERT INTO user_data (user_id, data) VALUES (, )', [userId, data]);
           res.status(200).send('User added successfully');
       } catch (err) {
           console.error(err);
           res.status(500).send('Error inserting user');
       }
   });

   app.get('/user/:userId', async (req, res) => {
       const userId = parseInt(req.params.userId, 10);
       const pool = getShardPool(userId);
       try {
           const result = await pool.query('SELECT * FROM user_data WHERE user_id = ', [userId]);
           res.status(200).json(result.rows);
       } catch (err) {
           console.error(err);
           res.status(500).send('Error retrieving user');
       }
   });

   app.listen(3000, () => console.log('Server running on port 3000'));

關鍵細節:

  1. 貼文分頁:遊標基於created_at字段或貼文中的另一個唯一字段,用於對結果進行分頁。
  2. 獨立查詢分片:由於貼文和使用者在不同的鍵上分片,因此我們獨立查詢每個分片,在應用程式層級執行聯接之前從所有分片收集資料。
  3. 遊標處理:檢索結果後,我們使用貼文中的last created_at(或post_id)來產生下一頁的遊標。
  4. 在應用程式層級加入:從相關分片取得資料後,我們根據記憶體中的 user_id 將貼文與使用者資料加入。

結論

管理分散式系統中的分片資料提出了獨特的挑戰,特別是在執行高效連接時。了解廣播連接分散-聚集連接等技術並利用分散式查詢引擎可以顯著提高查詢效能。此外,在應用程式層級查詢中,必須考慮分片鍵對齊非規範化和最佳化的查詢策略。透過遵循這些最佳實踐並利用正確的工具,開發人員可以確保他們的應用程式有效處理分片資料並大規模維持效能。

以上是處理分散式系統中的分割資料:深入探討連線、廣播和查詢最佳化的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
在JavaScript中替換字符串字符在JavaScript中替換字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

構建您自己的Ajax Web應用程序構建您自己的Ajax Web應用程序Mar 09, 2025 am 12:11 AM

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

10個JQuery Fun and Games插件10個JQuery Fun and Games插件Mar 08, 2025 am 12:42 AM

10款趣味橫生的jQuery遊戲插件,讓您的網站更具吸引力,提升用戶粘性!雖然Flash仍然是開發休閒網頁遊戲的最佳軟件,但jQuery也能創造出令人驚喜的效果,雖然無法與純動作Flash遊戲媲美,但在某些情況下,您也能在瀏覽器中獲得意想不到的樂趣。 jQuery井字棋遊戲 遊戲編程的“Hello world”,現在有了jQuery版本。 源碼 jQuery瘋狂填詞遊戲 這是一個填空遊戲,由於不知道單詞的上下文,可能會產生一些古怪的結果。 源碼 jQuery掃雷遊戲

如何創建和發布自己的JavaScript庫?如何創建和發布自己的JavaScript庫?Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

jQuery視差教程 - 動畫標題背景jQuery視差教程 - 動畫標題背景Mar 08, 2025 am 12:39 AM

本教程演示瞭如何使用jQuery創建迷人的視差背景效果。 我們將構建一個帶有分層圖像的標題橫幅,從而創造出令人驚嘆的視覺深度。 更新的插件可與JQuery 1.6.4及更高版本一起使用。 下載

如何在瀏覽器中優化JavaScript代碼以進行性能?如何在瀏覽器中優化JavaScript代碼以進行性能?Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

Matter.js入門:簡介Matter.js入門:簡介Mar 08, 2025 am 12:53 AM

Matter.js是一個用JavaScript編寫的2D剛體物理引擎。此庫可以幫助您輕鬆地在瀏覽器中模擬2D物理。它提供了許多功能,例如創建剛體並為其分配質量、面積或密度等物理屬性的能力。您還可以模擬不同類型的碰撞和力,例如重力摩擦力。 Matter.js支持所有主流瀏覽器。此外,它也適用於移動設備,因為它可以檢測觸摸並具有響應能力。所有這些功能都使其值得您投入時間學習如何使用該引擎,因為這樣您就可以輕鬆創建基於物理的2D遊戲或模擬。在本教程中,我將介紹此庫的基礎知識,包括其安裝和用法,並提供一

使用jQuery和Ajax自動刷新DIV內容使用jQuery和Ajax自動刷新DIV內容Mar 08, 2025 am 12:58 AM

本文演示瞭如何使用jQuery和ajax自動每5秒自動刷新DIV的內容。 該示例從RSS提要中獲取並顯示了最新的博客文章以及最後的刷新時間戳。 加載圖像是選擇

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。