張大朋(lunar)oracle 工程師
lunar 擁有超過十年的 oracle support 從業經驗,曾經服務于oracle acs部門,現就職于 oracle sales consultant 部門,負責的産品主要是 exadata,golden gate,database 等。
編輯說明:感謝lunar授權我們轉載其原創文章,文章插入了一些我們以前分享的圖檔,作為配合解讀。
2015年8月份内部release了oracle 12.2 beta版本(目前内部最新release的版本是2016年2月份釋出的,windows和linux都有了),目前根據12.2beta文檔的介紹,oracle推出了sharding的功能,跟其他nosql型的sharding結構相比,oracle sharding提供的是企業級的rdbms的分片技術。
oracle sharding的優點:
• relational schemas
• database partitioning
• acid properties and read consistency
• sql and other programmatic interfaces
• complex data types
• online schema changes
• multi-core scalability
• advanced security
• compression
• high availability features
• enterprise-scale backup and recovery
在oracle rdbms 12.2.0.1中最多支援1000個shards。
oracle sharding使用gds(global data services)架構來自動部署和管理sharding和複制技術。gds(gds是oracle rdbms 12.1的新特性)也提供負載均衡和sdb(sharded database)中的基于位置的路由功能。
shard目錄(shard directors)使用gds framework的全局服務管理元件(global service manager component)來提供應用層請求到shard的直接路由。shard目錄(shard directors)是一個單獨的資料庫,它用來儲存sdb(sharding database)配置資料和提供其他相關功能,比如shard的交叉查詢和集中管理。可以使用gds是gdsctl工具可以用來配置sdb。
oracle sharding的分區架構(partitioning infrastructure)
分區在表空間級别跨shards分布,每個表空間關聯一個特定的shard。一個shard表的每一個分區放單獨的表空間,并且每個表空間關聯到一個特定的shard。根據不同的sharding方法,這個關聯可以自動建立或者根據定義建立。盡管一個shard表的多個分區放在多個單獨主機的資料庫上(這些資料庫完全獨立,不共享cpu、記憶體等軟體和硬體),但是應用通路表時就如同通路一個單獨資料庫中的分區表一樣。應用發出的sql語句不需要依賴shard号和shard的實體配置。
oracle sharding 使用 familiar sql 文法建立表分區,指定分區表的每行資料如何分片。
一個shard表的分區鍵叫做sharding key,例如,下面的文法是典型的用來建立sharding表的:
create sharded table customers
( cust_id number not null
, name varchar2(50)
, address varchar2(250)
, region varchar2(20)
, class varchar2(3)
, signup date
constraint cust_pk primary key(cust_id)
)
partition by consistent hash (cust_id)
tablespace set ts1
partitions auto;
這個資料分片(shard)就是基于鍵值cust_id,分區采用“consistent hash”,這是一個特定的hash分區類型,通常用在分布式系統上。
.
sharding a table family
一個表家族(table family)中沒有任何父表的表叫做根表(root table),每個表家族中隻能有一個根表。
表家族中所有的表按照根表的主鍵進行sharding,根據各級表的結構,相關資料可以被存儲在同一個shard上。
在12.2,在一個sdb中隻支援一個表家族。
以下面的例子說明,這裡一共3張表組成的表家族(table family):客戶表,訂單表和訂單明細表。
每個客戶可以有多個訂單,每個訂單中可以有多個商品,是以訂單明細中就記錄了每個訂單中的多個商品,他們的具體資料如下:
在這個表族中,客戶編号為123的資料如下:
将一個表族(sharded table family)分片通常使有下面兩種方法建立:
方法1:不顯示指定父子關系,而是通過表之間主外鍵關系建立表族。
這種方式建立的表族是一個多級的樹形結構。
根表(root table)是客戶表:
–客戶表的主鍵是custno,分區方式是“consistent hash (custno)”
–儲存再表空間集ts1中
<code>create sharded table customers</code>
<code>( custno number not null</code>
<code>, name varchar2(50)</code>
<code>, address varchar2(250)</code>
<code>, constraint rootpk primary key(custno)</code>
<code>)</code>
<code>partition by consistent hash (custno)</code>
<code>partitions auto</code>
<code>tablespace set ts1</code>
<code>;</code>
–訂單表是客戶表的字表,子表(訂單表)根據custno關聯父表(客戶表):
–訂單表的主鍵是(custno, orderno),外鍵(custno)引用了主表customers(custno)
–分區方式是按照訂單表的外鍵限制(custfk)
<code>create sharded table orders</code>
<code>( orderno number not null</code>
<code>, custno number not null</code>
<code>, orderdate date</code>
<code>, constraint orderpk primary key (custno, orderno)</code>
<code>, constraint custfk foreign key (custno) references customers(custno)</code>
<code>partition by reference (custfk)</code>
–訂單明細表是訂單表的字表,子表(訂單明細表)根據custno關聯父表(訂單表)
–訂單明細表的主鍵是(custno, orderno, lineno),外鍵(custno, orderno)引用了父表orders(orderno)和orders(custno, orderno)
–分區方式是按照訂單明細表的外鍵限制(linefk)
<code>create sharded table lineitems</code>
<code>, lineno number(2) not null</code>
<code>, orderno number(5) not null</code>
<code>, stockno number(4)</code>
<code>, quantity number(2)</code>
<code>, constraint linepk primary key (custno, orderno, lineno)</code>
<code>, constraint linefk foreign key (custno, orderno) references orders(orderno)</code>
<code>references orders(custno, orderno)</code>
<code>partition by reference (linefk)</code>
是以,上面的例子中,這個表家族的所有資料都儲存在同一個表空間集ts1中。
當根表中增加一個分區的時候,那麼相關聯的表中都會自動增加相應的分區。
方法2:在分區表中顯示指定父子關系的方法建立表家族
這種分區方法隻支援兩級的表家族(two-level table families),所有的子表必須有相同的父表,父表的分區列在每個子表中都存在,例如下面的custno.
–沒有關鍵字“parent”(也沒有上面引用限制關鍵字)的是根表,即客戶表(customers)
<code>, region varchar2(20)</code>
<code>, class varchar2(3)</code>
<code>, signup date</code>
–根據關鍵字“parent customers”指定了訂單表(orders)的父表是客戶表(customers)
<code>( orderno number</code>
<code>, custno number</code>
<code>parent customers</code>
–根據關鍵字“parent customers”指定了訂單明細表(lineitems)的父表是客戶表(customers)
<code>( lineno number</code>
<code>, orderno number</code>
<code>, stockno number</code>
<code>, quantity number</code>
creating a duplicated table using create table
複制表可以被複制到所有的shard上,這種在每個shard上有相同内容的表叫做複制表(duplicated table),需要經常跟shard表關聯的小表适合于作為複制表(duplicated table),适用于:
(1)隻讀表
(2)大量跨shard的讀操作
oracle sharding使用materialized view replication來同步複制表(duplicated tables)的内容,每個shard上的duplicated tables的内容是一個隻讀物化視圖(read-only materialized view)。
物化視圖(materialized views)的主表儲存在一個專門的資料庫中,叫做shard catalog。
所有shard上的物化視圖(materialized views)會根據配置的頻率自動重新整理。
建立複制表的語句“create duplicated table”會自動建立master表,物化視圖和其他物化視圖複制所需要的對象。
還是以上面的客戶訂單關系為例,這裡定義産品表(products)為複制表:
<code>create duplicated table products</code>
<code>( stockno number primary key</code>
<code>, description varchar2(20)</code>
<code>, price number(6,2))</code>
根據sharding的機制,sharding的設計對後續系統性能影響是非常大的。一旦sharding建立完成,并已經有很多資料,相關的屬性就不能再修改了,比如某個表是複制表,還是sharding表,sharding key等等,是以,sdb的設計是至關重要的,在設計sharding時需要考慮的有:
哪些表需要被設計為sharding表; 哪些表需要做複制表; 哪些shard表是根表; 使用什麼方法來關聯一個表到其他表或者根表; 應該使用哪種sharding方法; 使用哪個作為sharding key;