mirror of
https://github.com/Vonng/ddia.git
synced 2025-04-05 15:50:09 +08:00
Merge branch 'Vonng:master' into master
This commit is contained in:
commit
c9ffbb3a21
@ -152,6 +152,7 @@
|
||||
|
||||
| ISSUE & Pull Requests | USER | Title |
|
||||
| ----------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| [134](https://github.com/Vonng/ddia/pull/134) | [@fuxuemingzhu](https://github.com/fuxuemingzhu) | ch4: 优化多处不通顺的或错误的翻译 |
|
||||
| [133](https://github.com/Vonng/ddia/pull/133) | [@fuxuemingzhu](https://github.com/fuxuemingzhu) | ch3: 优化多处错误的或不通顺的翻译 |
|
||||
| [132](https://github.com/Vonng/ddia/pull/132) | [@fuxuemingzhu](https://github.com/fuxuemingzhu) | ch3: 优化一处容易产生歧义的翻译 |
|
||||
| [131](https://github.com/Vonng/ddia/pull/131) | [@rwwg4](https://github.com/rwwg4) | ch6: 修正两处错误的翻译 |
|
||||
|
@ -152,6 +152,8 @@
|
||||
|
||||
| ISSUE & Pull Requests | USER | Title |
|
||||
| ----------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| [134](https://github.com/Vonng/ddia/pull/134) | [@fuxuemingzhu](https://github.com/fuxuemingzhu) | ch4: 最佳化多處不通順的或錯誤的翻譯 |
|
||||
| [133](https://github.com/Vonng/ddia/pull/133) | [@fuxuemingzhu](https://github.com/fuxuemingzhu) | ch3: 最佳化多處錯誤的或不通順的翻譯 |
|
||||
| [132](https://github.com/Vonng/ddia/pull/132) | [@fuxuemingzhu](https://github.com/fuxuemingzhu) | ch3: 最佳化一處容易產生歧義的翻譯 |
|
||||
| [131](https://github.com/Vonng/ddia/pull/131) | [@rwwg4](https://github.com/rwwg4) | ch6: 修正兩處錯誤的翻譯 |
|
||||
| [129](https://github.com/Vonng/ddia/pull/129) | [@anaer](https://github.com/anaer) | ch4: 修正兩處強調文字和四處程式碼變數名稱 |
|
||||
|
10
zh-tw/ch3.md
10
zh-tw/ch3.md
@ -370,7 +370,7 @@ SELECT * FROM restaurants WHERE latitude > 51.4946 AND latitude < 51.5079
|
||||
|
||||
在早期業務資料處理過程中,一次典型的資料庫寫入通常與一筆 *商業交易(commercial transaction)* 相對應:賣個貨,向供應商下訂單,支付員工工資等等。但隨著資料庫應用至那些不涉及到錢的領域,術語 **交易/事務(transaction)** 仍留了下來,用於指代一組讀寫操作構成的邏輯單元。
|
||||
|
||||
事務不一定具有ACID(原子性,一致性,隔離性和永續性)屬性。事務處理只是意味著允許客戶端進行低延遲讀取和寫入 —— 而不是批次處理作業,而這些作業只能定期執行(例如每天一次)。我們在[第七章](ch7.md)中討論ACID屬性,在[第十章](ch10.md)中討論批處理。
|
||||
事務不一定具有ACID(原子性,一致性,隔離性和永續性)屬性。事務處理只是意味著允許客戶端進行低延遲讀取和寫入 —— 而不是隻能定期執行(例如每天一次)的批次處理作業。我們在[第七章](ch7.md)中討論ACID屬性,在[第十章](ch10.md)中討論批處理。
|
||||
|
||||
即使資料庫開始被用於許多不同型別的資料,比如部落格文章的評論,遊戲中的動作,地址簿中的聯絡人等等,基本訪問模式仍然類似於處理商業交易。應用程式通常使用索引透過某個鍵查詢少量記錄。根據使用者的輸入插入或更新記錄。由於這些應用程式是互動式的,這種訪問模式被稱為 **線上事務處理(OLTP, OnLine Transaction Processing)** 。
|
||||
|
||||
@ -422,7 +422,7 @@ Teradata,Vertica,SAP HANA和ParAccel等資料倉庫供應商通常使用昂
|
||||
|
||||
### 星型和雪花型:分析的模式
|
||||
|
||||
正如[第二章](ch2.md)所探討的,根據應用程式的需要,在事務處理領域中使用了大量不同的資料模型。另一方面,在分析中,資料模型的多樣性則少得多。許多資料倉庫都以相當公式化的方式使用,被稱為星型模式(也稱為維度建模【55】)。
|
||||
正如[第二章](ch2.md)所探討的,根據應用程式的需要,在事務處理領域中使用了大量不同的資料模型。另一方面,在分析型業務中,資料模型的多樣性則少得多。許多資料倉庫都以相當公式化的方式使用,被稱為星型模式(也稱為維度建模【55】)。
|
||||
|
||||
圖3-9中的示例模式顯示了可能在食品零售商處找到的資料倉庫。在模式的中心是一個所謂的事實表(在這個例子中,它被稱為 `fact_sales`)。事實表的每一行代表在特定時間發生的事件(這裡,每一行代表客戶購買的產品)。如果我們分析的是網站流量而不是零售量,則每行可能代表一個使用者的頁面瀏覽量或點選量。
|
||||
|
||||
@ -430,7 +430,7 @@ Teradata,Vertica,SAP HANA和ParAccel等資料倉庫供應商通常使用昂
|
||||
|
||||
**圖3-9 用於資料倉庫的星型模式的示例**
|
||||
|
||||
通常情況下,事實被視為單獨的事件,因為這樣可以在以後分析中獲得最大的靈活性。但是,這意味著事實表可以變得非常大。像蘋果,沃爾瑪或eBay這樣的大企業在其資料倉庫中可能有幾十PB的交易歷史,其中大部分實際上是表【56】。
|
||||
通常情況下,事實被視為單獨的事件,因為這樣可以在以後分析中獲得最大的靈活性。但是,這意味著事實表可以變得非常大。像蘋果,沃爾瑪或eBay這樣的大企業在其資料倉庫中可能有幾十PB的交易歷史,其中大部分儲存在事實表中【56】。
|
||||
|
||||
事實表中的一些列是屬性,例如產品銷售的價格和從供應商那裡購買的成本(允許計算利潤餘額)。事實表中的其他列是對其他表(稱為維度表)的外來鍵引用。由於事實表中的每一行都表示一個事件,因此這些維度代表事件的發生地點,時間,方式和原因。
|
||||
|
||||
@ -448,7 +448,7 @@ Teradata,Vertica,SAP HANA和ParAccel等資料倉庫供應商通常使用昂
|
||||
|
||||
## 列儲存
|
||||
|
||||
如果事實表中有萬億行和數PB的資料,那麼高效地儲存和查詢它們就成為一個具有挑戰性的問題。維度表通常要小得多(數百萬行),所以在本節中我們將主要關注事實的儲存。
|
||||
如果事實表中有萬億行和數PB的資料,那麼高效地儲存和查詢它們就成為一個具有挑戰性的問題。維度表通常要小得多(數百萬行),所以在本節中我們將主要關注事實表的儲存。
|
||||
|
||||
儘管事實表通常超過100列,但典型的資料倉庫查詢一次只能訪問4個或5個查詢( “ `SELECT *` ” 查詢很少用於分析)【51】。以[例3-1]()中的查詢為例:它訪問了大量的行(在2013日曆年中每次都有人購買水果或糖果),但只需訪問`fact_sales`表的三列:`date_key, product_sk, quantity`。查詢忽略所有其他列。
|
||||
|
||||
@ -542,7 +542,7 @@ WHERE product_sk = 31 AND store_sk = 3
|
||||
|
||||
排序順序的另一個好處是它可以幫助壓縮列。如果主要排序列沒有多個不同的值,那麼在排序之後,它將具有很長的序列,其中相同的值連續重複多次。一個簡單的遊程編碼(就像我們用於[圖3-11](../img/fig3-11.png)中的點陣圖一樣)可以將該列壓縮到幾千位元組 —— 即使表中有數十億行。
|
||||
|
||||
第一個排序鍵的壓縮效果最強。第二和第三個排序鍵會更混亂,因此不會有這麼長時間的重複值。排序優先順序更低的列以基本上隨機的順序出現,所以它們可能不會被壓縮。但前幾列排序在整體上仍然是有好外的。
|
||||
第一個排序鍵的壓縮效果最強。第二和第三個排序鍵會更混亂,因此不會有這麼長時間的重複值。排序優先順序更低的列以基本上隨機的順序出現,所以它們可能不會被壓縮。但前幾列排序在整體上仍然是有好處的。
|
||||
|
||||
#### 幾個不同的排序順序
|
||||
|
||||
|
18
zh-tw/ch4.md
18
zh-tw/ch4.md
@ -154,7 +154,7 @@ Thrift和Protocol Buffers每一個都帶有一個程式碼生成工具,它採
|
||||
|
||||
與[圖4-1](../img/fig4-1.png)相比,最大的區別是沒有欄位名`(userName, favoriteNumber, interests)`。相反,編碼資料包含欄位標籤,它們是數字`(1, 2和3)`。這些是模式定義中出現的數字。欄位標記就像欄位的別名 - 它們是說我們正在談論的欄位的一種緊湊的方式,而不必拼出欄位名稱。
|
||||
|
||||
Thrift CompactProtocol編碼在語義上等同於BinaryProtocol,但是如[圖4-3](../img/fig4-3.png)所示,它只將相同的資訊打包成只有34個位元組。它透過將欄位型別和標籤號打包到單個位元組中,並使用可變長度整數來實現。數字1337不是使用全部八個位元組,而是用兩個位元組編碼,每個位元組的最高位用來指示是否還有更多的位元組來。這意味著-64到63之間的數字被編碼為一個位元組,-8192和8191之間的數字以兩個位元組編碼,等等。較大的數字使用更多的位元組。
|
||||
Thrift CompactProtocol編碼在語義上等同於BinaryProtocol,但是如[圖4-3](../img/fig4-3.png)所示,它只將相同的資訊打包成只有34個位元組。它透過將欄位型別和標籤號打包到單個位元組中,並使用可變長度整數來實現。數字1337不是使用全部八個位元組,而是用兩個位元組編碼,每個位元組的最高位用來指示是否還有更多的位元組。這意味著-64到63之間的數字被編碼為一個位元組,-8192和8191之間的數字以兩個位元組編碼,等等。較大的數字使用更多的位元組。
|
||||
|
||||

|
||||
|
||||
@ -166,7 +166,7 @@ Thrift CompactProtocol編碼在語義上等同於BinaryProtocol,但是如[圖4
|
||||
|
||||
**圖4-4 使用Protobuf編碼的記錄**
|
||||
|
||||
需要注意的一個細節:在前面所示的模式中,每個欄位被標記為必需或可選,但是這對欄位如何編碼沒有任何影響(二進位制資料中沒有任何欄位指示是否需要欄位)。所不同的是,如果未設定該欄位,則所需的執行時檢查將失敗,這對於捕獲錯誤非常有用。
|
||||
需要注意的一個細節:在前面所示的模式中,每個欄位被標記為必需或可選,但是這對欄位如何編碼沒有任何影響(二進位制資料中沒有任何欄位指示某欄位是否必須)。區別在於,如果欄位設定為 `required`,但未設定該欄位,則所需的執行時檢查將失敗,這對於捕獲錯誤非常有用。
|
||||
|
||||
#### 欄位標籤和模式演變
|
||||
|
||||
@ -174,7 +174,7 @@ Thrift CompactProtocol編碼在語義上等同於BinaryProtocol,但是如[圖4
|
||||
|
||||
從示例中可以看出,編碼的記錄就是其編碼欄位的拼接。每個欄位由其標籤號碼(樣本模式中的數字1,2,3)標識,並用資料型別(例如字串或整數)註釋。如果沒有設定欄位值,則簡單地從編碼記錄中省略。從中可以看到,欄位標記對編碼資料的含義至關重要。您可以更改架構中欄位的名稱,因為編碼的資料永遠不會引用欄位名稱,但不能更改欄位的標記,因為這會使所有現有的編碼資料無效。
|
||||
|
||||
您可以新增新的欄位到架構,只要您給每個欄位一個新的標籤號碼。如果舊的程式碼(不知道你新增的新的標籤號碼)試圖讀取新程式碼寫入的資料,包括一個新的欄位,其標籤號碼不能識別,它可以簡單地忽略該欄位。資料型別註釋允許解析器確定需要跳過的位元組數。這保持了前向相容性:舊程式碼可以讀取由新程式碼編寫的記錄。
|
||||
您可以新增新的欄位到架構,只要您給每個欄位一個新的標籤號碼。如果舊的程式碼(不知道你新增的新的標籤號碼)試圖讀取新程式碼寫入的資料,包括一個新的欄位,其標籤號碼不能識別,它可以簡單地忽略該欄位。資料型別註釋允許解析器確定需要跳過的位元組數。這保持了向前相容性:舊程式碼可以讀取由新程式碼編寫的記錄。
|
||||
|
||||
向後相容性呢?只要每個欄位都有一個唯一的標籤號碼,新的程式碼總是可以讀取舊的資料,因為標籤號碼仍然具有相同的含義。唯一的細節是,如果你新增一個新的欄位,你不能設定為必需。如果您要新增一個欄位並將其設定為必需,那麼如果新程式碼讀取舊程式碼寫入的資料,則該檢查將失敗,因為舊程式碼不會寫入您新增的新欄位。因此,為了保持向後相容性,在模式的初始部署之後 **新增的每個欄位必須是可選的或具有預設值**。
|
||||
|
||||
@ -184,13 +184,13 @@ Thrift CompactProtocol編碼在語義上等同於BinaryProtocol,但是如[圖4
|
||||
|
||||
如何改變欄位的資料型別?這也許是可能的——詳細資訊請查閱相關的文件——但是有一個風險,值將失去精度或被截斷。例如,假設你將一個32位的整數變成一個64位的整數。新程式碼可以輕鬆讀取舊程式碼寫入的資料,因為解析器可以用零填充任何缺失的位。但是,如果舊程式碼讀取由新程式碼寫入的資料,則舊程式碼仍使用32位變數來儲存該值。如果解碼的64位值不適合32位,則它將被截斷。
|
||||
|
||||
Protobuf的一個奇怪的細節是,它沒有列表或陣列資料型別,而是有一個欄位的重複標記(這是除必需和可選之外的第三個選項)。如[圖4-4](../img/fig4-4.png)所示,重複欄位的編碼正如它所說的那樣:同一個欄位標記只是簡單地出現在記錄中。這具有很好的效果,可以將可選(單值)欄位更改為重複(多值)欄位。讀取舊資料的新程式碼會看到一個包含零個或一個元素的列表(取決於該欄位是否存在)。讀取新資料的舊程式碼只能看到列表的最後一個元素。
|
||||
Protobuf的一個奇怪的細節是,它沒有列表或陣列資料型別,而是有一個欄位的重複標記(`repeated`,這是除必需和可選之外的第三個選項)。如[圖4-4](../img/fig4-4.png)所示,重複欄位的編碼正如它所說的那樣:同一個欄位標記只是簡單地出現在記錄中。這具有很好的效果,可以將可選(單值)欄位更改為重複(多值)欄位。讀取舊資料的新程式碼會看到一個包含零個或一個元素的列表(取決於該欄位是否存在)。讀取新資料的舊程式碼只能看到列表的最後一個元素。
|
||||
|
||||
Thrift有一個專用的列表資料型別,它使用列表元素的資料型別進行引數化。這不允許Protocol Buffers所做的從單值到多值的演變,但是它具有支援巢狀列表的優點。
|
||||
|
||||
### Avro
|
||||
|
||||
Apache Avro 【20】是另一種二進位制編碼格式,與Protocol Buffers和Thrift有趣的不同。 它是作為Hadoop的一個子專案在2009年開始的,因為Thrift不適合Hadoop的用例【21】。
|
||||
Apache Avro 【20】是另一種二進位制編碼格式,與Protocol Buffers和Thrift有著有趣的不同。 它是作為Hadoop的一個子專案在2009年開始的,因為Thrift不適合Hadoop的用例【21】。
|
||||
|
||||
Avro也使用模式來指定正在編碼的資料的結構。 它有兩種模式語言:一種(Avro IDL)用於人工編輯,一種(基於JSON)更易於機器讀取。
|
||||
|
||||
@ -292,7 +292,7 @@ Avro的關鍵思想是Writer模式和Reader模式不必是相同的 - 他們只
|
||||
|
||||
Thrift和Protobuf依賴於程式碼生成:在定義了模式之後,可以使用您選擇的程式語言生成實現此模式的程式碼。這在Java,C ++或C#等靜態型別語言中很有用,因為它允許將高效的記憶體中結構用於解碼的資料,並且在編寫訪問資料結構的程式時允許在IDE中進行型別檢查和自動完成。
|
||||
|
||||
在動態型別程式語言(如JavaScript,Ruby或Python)中,生成程式碼沒有太多意義,因為沒有編譯時型別檢查器來滿足。程式碼生成在這些語言中經常被忽視,因為它們避免了顯示的編譯步驟。而且,對於動態生成的模式(例如從資料庫表生成的Avro模式),程式碼生成對獲取資料是一個不必要的障礙。
|
||||
在動態型別程式語言(如JavaScript,Ruby或Python)中,生成程式碼沒有太多意義,因為沒有編譯時型別檢查器來滿足。程式碼生成在這些語言中經常被忽視,因為它們避免了顯式的編譯步驟。而且,對於動態生成的模式(例如從資料庫表生成的Avro模式),程式碼生成對獲取資料是一個不必要的障礙。
|
||||
|
||||
Avro為靜態型別程式語言提供了可選的程式碼生成功能,但是它也可以在不生成任何程式碼的情況下使用。如果你有一個物件容器檔案(它嵌入了Writer模式),你可以簡單地使用Avro庫開啟它,並以與檢視JSON檔案相同的方式檢視資料。該檔案是自描述的,因為它包含所有必要的元資料。
|
||||
|
||||
@ -425,7 +425,7 @@ Web服務僅僅是透過網路進行API請求的一系列技術的最新版本
|
||||
* 每次呼叫本地功能時,通常需要大致相同的時間來執行。網路請求比函式呼叫要慢得多,而且其延遲也是非常可變的:好的時候它可能會在不到一毫秒的時間內完成,但是當網路擁塞或者遠端服務超載時,可能需要幾秒鐘的時間完成一樣的東西。
|
||||
* 呼叫本地函式時,可以高效地將引用(指標)傳遞給本地記憶體中的物件。當你發出一個網路請求時,所有這些引數都需要被編碼成可以透過網路傳送的一系列位元組。如果引數是像數字或字串這樣的基本型別倒是沒關係,但是對於較大的物件很快就會變成問題。
|
||||
|
||||
客戶端和服務可以用不同的程式語言實現,所以RPC框架必須將資料型別從一種語言翻譯成另一種語言。這可能會捅出大簍子,因為不是所有的語言都具有相同的型別 —— 例如回想一下JavaScript的數字大於$2^{53}$的問題(請參閱“[JSON,XML和二進位制變體](#JSON,XML和二進位制變體)”)。用單一語言編寫的單個程序中不存在此問題。
|
||||
- 客戶端和服務可以用不同的程式語言實現,所以RPC框架必須將資料型別從一種語言翻譯成另一種語言。這可能會捅出大簍子,因為不是所有的語言都具有相同的型別 —— 例如回想一下JavaScript的數字大於$2^{53}$的問題(請參閱“[JSON,XML和二進位制變體](#JSON,XML和二進位制變體)”)。用單一語言編寫的單個程序中不存在此問題。
|
||||
|
||||
所有這些因素意味著嘗試使遠端服務看起來像程式語言中的本地物件一樣毫無意義,因為這是一個根本不同的事情。 REST的部分吸引力在於,它並不試圖隱藏它是一個網路協議的事實(儘管這似乎並沒有阻止人們在REST之上構建RPC庫)。
|
||||
|
||||
@ -479,13 +479,13 @@ RPC方案的前後向相容性屬性從它使用的編碼方式中繼承:
|
||||
|
||||
一個主題只提供單向資料流。但是,消費者本身可能會將訊息釋出到另一個主題上(因此,可以將它們連結在一起,就像我們將在[第十一章](ch11.md)中看到的那樣),或者傳送給原始訊息的傳送者使用的回覆佇列(允許請求/響應資料流,類似於RPC)。
|
||||
|
||||
訊息代理通常不會執行任何特定的資料模型 - 訊息只是包含一些元資料的位元組序列,因此您可以使用任何編碼格式。如果編碼是向後和向前相容的,您可以靈活地對釋出者和消費者的編碼進行獨立的修改,並以任意順序進行部署。
|
||||
訊息代理通常不會執行任何特定的資料模型 —— 訊息只是包含一些元資料的位元組序列,因此您可以使用任何編碼格式。如果編碼是向後和向前相容的,您可以靈活地對釋出者和消費者的編碼進行獨立的修改,並以任意順序進行部署。
|
||||
|
||||
如果消費者重新發布訊息到另一個主題,則可能需要小心保留未知欄位,以防止前面在資料庫環境中描述的問題([圖4-7](../img/fig4-7.png))。
|
||||
|
||||
#### 分散式的Actor框架
|
||||
|
||||
Actor模型是單個程序中併發的程式設計模型。邏輯被封裝在actor中,而不是直接處理執行緒(以及競爭條件,鎖定和死鎖的相關問題)。每個actor通常代表一個客戶或實體,它可能有一些本地狀態(不與其他任何角色共享),它透過傳送和接收非同步訊息與其他角色通訊。訊息傳送不保證:在某些錯誤情況下,訊息將丟失。由於每個角色一次只能處理一條訊息,因此不需要擔心執行緒,每個角色可以由框架獨立排程。
|
||||
Actor模型是單個程序中併發的程式設計模型。邏輯被封裝在actor中,而不是直接處理執行緒(以及競爭條件,鎖定和死鎖的相關問題)。每個actor通常代表一個客戶或實體,它可能有一些本地狀態(不與其他任何角色共享),它透過傳送和接收非同步訊息與其他角色通訊。不保證訊息傳送:在某些錯誤情況下,訊息將丟失。由於每個角色一次只能處理一條訊息,因此不需要擔心執行緒,每個角色可以由框架獨立排程。
|
||||
|
||||
在分散式Actor框架中,此程式設計模型用於跨多個節點伸縮應用程式。不管傳送方和接收方是在同一個節點上還是在不同的節點上,都使用相同的訊息傳遞機制。如果它們在不同的節點上,則該訊息被透明地編碼成位元組序列,透過網路傳送,並在另一側解碼。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user