日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

数据库表设计、 数据库分层、myslq水平拆分、oracle表分区

發(fā)布時(shí)間:2024/4/13 数据库 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库表设计、 数据库分层、myslq水平拆分、oracle表分区 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

數(shù)據(jù)庫(kù)表設(shè)計(jì)

數(shù)據(jù)庫(kù)表結(jié)構(gòu)設(shè)計(jì)方法及原則(li)數(shù)據(jù)庫(kù)設(shè)計(jì)的三大范式:為了建立冗余較小、結(jié)構(gòu)合理的數(shù)據(jù)庫(kù),設(shè)計(jì)數(shù)據(jù)庫(kù)時(shí)必須遵循一定的規(guī)則。在關(guān)系型數(shù)據(jù)庫(kù)中這種規(guī)則就稱為范式。范式是符合某一種設(shè)計(jì)要求的總結(jié)。要想設(shè)計(jì)一個(gè)結(jié)構(gòu)合理的關(guān)系型數(shù)據(jù)庫(kù),必須滿足一定的范式。在實(shí)際開(kāi)發(fā)中最為常見(jiàn)的設(shè)計(jì)范式有三個(gè):第一范式是最基本的范式。如果數(shù)據(jù)庫(kù)表中的所有字段值都是不可分解的原子值,就說(shuō)明該數(shù)據(jù)庫(kù)表滿足了第一范式;第二范式在第一范式的基礎(chǔ)之上更進(jìn)一層。第二范式需要確保數(shù)據(jù)庫(kù)表中的每一列都和主鍵相關(guān),而不能只與主鍵的某一部分相關(guān)(主要針對(duì)聯(lián)合主鍵而言)。也就是說(shuō)在一個(gè)數(shù)據(jù)庫(kù)表中,一個(gè)表中只能保存一種數(shù)據(jù),不可以把多種數(shù)據(jù)保存在同一張數(shù)據(jù)庫(kù)表中;第三范式需要確保數(shù)據(jù)表中的每一列數(shù)據(jù)都和主鍵直接相關(guān),而不能間接相關(guān)??偨Y(jié)一下,就是:第一范式(確保每列保持原子性);第二范式(確保表中的每列都和主鍵相關(guān));第三范式(確保每列都和主鍵列直接相關(guān),而不是間接相關(guān))。在目前的企業(yè)信息系統(tǒng)中,數(shù)據(jù)庫(kù)還是最佳的數(shù)據(jù)存儲(chǔ)方式,雖然已經(jīng)有很多的書籍在指導(dǎo)我們進(jìn)行數(shù)據(jù)庫(kù)設(shè)計(jì),但應(yīng)該那種方式是設(shè)計(jì)數(shù)據(jù)庫(kù)的表結(jié)構(gòu)的最好方法、設(shè)計(jì)時(shí)應(yīng)遵從什么樣的原則、四個(gè)范式如何能夠用一種方式達(dá)到順暢的應(yīng)用等是我一直在思考和總結(jié)的問(wèn)題,下文是我針對(duì)這幾個(gè)問(wèn)題根據(jù)自己的設(shè)計(jì)經(jīng)歷準(zhǔn)備總結(jié)的一篇文章的提綱,歡迎大家一塊進(jìn)行探討,集思廣益。其中提到了領(lǐng)域建模的概念,但未作詳細(xì)解釋,希望以后能夠有時(shí)間我們針對(duì)這個(gè)命題進(jìn)行深入探討。1.不應(yīng)該針對(duì)整個(gè)系統(tǒng)進(jìn)行數(shù)據(jù)庫(kù)設(shè)計(jì),而應(yīng)該根據(jù)系統(tǒng)架構(gòu)中的組件劃分,針對(duì)每個(gè)組件所處理的業(yè)務(wù)進(jìn)行組件單元的數(shù)據(jù)庫(kù)設(shè)計(jì);不同組件間所對(duì)應(yīng)的數(shù)據(jù)庫(kù)表之間的關(guān)聯(lián)應(yīng)盡可能減少,如果不同組件間的表需要外鍵關(guān)聯(lián)也盡量不要?jiǎng)?chuàng)建外鍵關(guān)聯(lián),而只是記錄關(guān)聯(lián)表的一個(gè)主鍵,確保組件對(duì)應(yīng)的表之間的獨(dú)立性,為系統(tǒng)或表結(jié)構(gòu)的重構(gòu)提供可能性。//注意他這里說(shuō)的是"不要?jiǎng)?chuàng)建外鍵關(guān)聯(lián)",創(chuàng)建外鍵關(guān)聯(lián)的語(yǔ)句是: //foreign key(member_id) references member (id); //我們幾乎沒(méi)有用到這條語(yǔ)句,因?yàn)槲覀兙褪沁@樣做的,用到外鍵時(shí),只是記錄關(guān)聯(lián)表的主鍵,而非在數(shù)據(jù)庫(kù)級(jí)別上創(chuàng)建外鍵。 //也不知道是歪打正著,還是前輩DBA過(guò)于強(qiáng)大,已經(jīng)考慮好了。2.采用領(lǐng)域模型驅(qū)動(dòng)的方式和自頂向下的思路進(jìn)行數(shù)據(jù)庫(kù)設(shè)計(jì),首先分析系統(tǒng)業(yè)務(wù),根據(jù)職責(zé)定義對(duì)象。對(duì)象要符合封裝的特性,確保與職責(zé)相關(guān)的數(shù)據(jù)項(xiàng)被定義在一個(gè)對(duì)象之內(nèi),這些數(shù)據(jù)項(xiàng)能夠完整描述該職責(zé),不會(huì)出現(xiàn)職責(zé)描述缺失。并且一個(gè)對(duì)象有且只有一項(xiàng)職責(zé),如果一個(gè)對(duì)象要負(fù)責(zé)兩個(gè)或兩個(gè)以上的職責(zé),應(yīng)進(jìn)行分拆。// 領(lǐng)域模型驅(qū)動(dòng)的方式,目前用的還不是很熟,考慮的不夠多。因?yàn)榻?jīng)常的數(shù)據(jù)庫(kù)中的表只是拿來(lái)做存儲(chǔ)用而已, //特別是小需求,要加什么字段,找到相關(guān)表加上去就行了,不太考慮領(lǐng)域模型。這個(gè)在中文站老業(yè)務(wù)表里很常見(jiàn)3.根據(jù)建立的領(lǐng)域模型進(jìn)行數(shù)據(jù)庫(kù)表的映射,此時(shí)應(yīng)參考數(shù)據(jù)庫(kù)設(shè)計(jì)第二范式:一個(gè)表中的所有非關(guān)鍵字屬性都依賴于整個(gè)關(guān)鍵字。關(guān)鍵字可以是一個(gè)屬性,也可以是多個(gè)屬性的集合,不論那種方式,都應(yīng)確保關(guān)鍵字能夠保證唯一性。在確定關(guān)鍵字時(shí),應(yīng)保證關(guān)鍵字不會(huì)參與業(yè)務(wù)且不會(huì)出現(xiàn)更新異常,這時(shí),最優(yōu)解決方案為采用一個(gè)自增數(shù)值型屬性或一個(gè)隨機(jī)字符串作為表的關(guān)鍵字。4.由于第一點(diǎn)所述的領(lǐng)域模型驅(qū)動(dòng)的方式設(shè)計(jì)數(shù)據(jù)庫(kù)表結(jié)構(gòu),領(lǐng)域模型中的每一個(gè)對(duì)象只有一項(xiàng)職責(zé),所以對(duì)象中的數(shù)據(jù)項(xiàng)不存在傳遞依賴,所以,這種思路的數(shù)據(jù)庫(kù)表結(jié)構(gòu)設(shè)計(jì)從一開(kāi)始即滿足第三范式:一個(gè)表應(yīng)滿足第二范式,且屬性間不存在傳遞依賴。//數(shù)據(jù)庫(kù)三范式記不得的同學(xué)去查資料溫習(xí)一下。 //個(gè)人認(rèn)為第三范式的目的是盡量減少數(shù)據(jù)冗余,保證相同的數(shù)據(jù)只存在一份。 //第三范式其實(shí)我們遵守的并不是很嚴(yán)格,特別是老的數(shù)據(jù)庫(kù)表中會(huì)有冗余字段。這個(gè)要看情況決定吧。5.同樣,由于對(duì)象職責(zé)的單一性以及對(duì)象之間的關(guān)系反映的是業(yè)務(wù)邏輯之間的關(guān)系,所以在領(lǐng)域模型中的對(duì)象存在主對(duì)象和從對(duì)象之分,從對(duì)象是從1-N或N-N的角度進(jìn)一步完善主對(duì)象的業(yè)務(wù)邏輯,所以從對(duì)象及對(duì)象關(guān)系映射為的表及表關(guān)聯(lián)關(guān)系不存在刪除和插入異常。//最后一句看不懂,可能是"所以表及表關(guān)聯(lián)關(guān)系不應(yīng)該出現(xiàn)刪除和插入異常。"?6.在映射后得出的數(shù)據(jù)庫(kù)表結(jié)構(gòu)中,應(yīng)再根據(jù)第四范式進(jìn)行進(jìn)一步修改,確保不存在多值依賴。這時(shí),應(yīng)根據(jù)反向工程的思路反饋給領(lǐng)域模型。如果表結(jié)構(gòu)中存在多值依賴,則證明領(lǐng)域模型中的對(duì)象具有至少兩個(gè)以上的職責(zé),應(yīng)根據(jù)第一條進(jìn)行設(shè)計(jì)修正。第四范式:一個(gè)表如果滿足BCNF,不應(yīng)存在多值依賴。 復(fù)制代碼 //第四范式我們遵守的并不多吧。 //例如: //VAS_WP_CONFIG.config_name字段的值包括:adv(廣告主題)/glare(炫彩滾動(dòng)主題)/theme_simple(普通主題)/theme_cartoon(動(dòng)畫主題)/ theme_none(不顯示背景主題) //cate_background(類目背景)/video(公司視頻)/board_cartoon(動(dòng)畫招牌)/board_simple(普通招牌)等。 //如果遵守第四范式,則需要新增一張VAS_WP_CONFIG_NAME表,存儲(chǔ)配置名稱枚舉值,而VAS_WP_CONFIG.config_name字段改為VAS_WP_CONFIG.config_name_id。 //這樣做更利于擴(kuò)展,不會(huì)因?yàn)槊總€(gè)人的理解不一致而向VAS_WP_CONFIG.config_name字段里設(shè)置亂七八糟的值,但是這樣需要維護(hù)更多的小表,造成數(shù)據(jù)值表的數(shù)量膨脹,DBA可能會(huì)覺(jué)得管理上有更多的困難。 //我們采用潛規(guī)則約定、java枚舉類等其它方式來(lái)進(jìn)行保證。但有時(shí)候效果并不是很好,經(jīng)常發(fā)現(xiàn)舊數(shù)據(jù)庫(kù)表中枚舉字段的值五花八門,不全是約定的。 復(fù)制代碼7.在經(jīng)過(guò)分析后確認(rèn)所有的表都滿足二、三、四范式的情況下,表和表之間的關(guān)聯(lián)盡量采用弱關(guān)聯(lián)以便于對(duì)表字段和表結(jié)構(gòu)的調(diào)整和重構(gòu)。并且,我認(rèn)為數(shù)據(jù)庫(kù)中的表是用來(lái)持久化一個(gè)對(duì)象實(shí)例在特定時(shí)間及特定條件下的狀態(tài)的,只是一個(gè)存儲(chǔ)介質(zhì),所以,表和表之間也不應(yīng)用強(qiáng)關(guān)聯(lián)來(lái)表述業(yè)務(wù)(數(shù)據(jù)間的一致性),這一職責(zé)應(yīng)由系統(tǒng)的邏輯層來(lái)保證,這種方式也確保了系統(tǒng)對(duì)于不正確數(shù)據(jù)(臟數(shù)據(jù))的兼容性。當(dāng)然,從整個(gè)系統(tǒng)的角度來(lái)說(shuō)我們還是要盡最大努力確保系統(tǒng)不會(huì)產(chǎn)生臟數(shù)據(jù),單從另一個(gè)角度來(lái)說(shuō),臟數(shù)據(jù)的產(chǎn)生在一定程度上也是不可避免的,我們也要保證系統(tǒng)對(duì)這種情況的容錯(cuò)性。這是一個(gè)折中的方案。8.應(yīng)針對(duì)所有表的主鍵和外鍵建立索引,有針對(duì)性的(針對(duì)一些大數(shù)據(jù)量和常用檢索方式)建立組合屬性的索引,提高檢索效率。雖然建立索引會(huì)消耗部分系統(tǒng)資源,但比較起在檢索時(shí)搜索整張表中的數(shù)據(jù)尤其時(shí)表中的數(shù)據(jù)量較大時(shí)所帶來(lái)的性能影響,以及無(wú)索引時(shí)的排序操作所帶來(lái)的性能影響,這種方式仍然是值得提倡的。//索引目前都是DBA根據(jù)具體的SQL來(lái)創(chuàng)建的,不過(guò)開(kāi)發(fā)寫SQL時(shí),也應(yīng)該適當(dāng)考慮一下字段的索引。9.盡量少采用存儲(chǔ)過(guò)程,目前已經(jīng)有很多技術(shù)可以替代存儲(chǔ)過(guò)程的功能如"對(duì)象/關(guān)系映射"等,將數(shù)據(jù)一致性的保證放在數(shù)據(jù)庫(kù)中,無(wú)論對(duì)于版本控制、開(kāi)發(fā)和部署、以及數(shù)據(jù)庫(kù)的遷移都會(huì)帶來(lái)很大的影響。但不可否認(rèn),存儲(chǔ)過(guò)程具有性能上的優(yōu)勢(shì),所以,當(dāng)系統(tǒng)可使用的硬件不會(huì)得到提升而性能又是非常重要的質(zhì)量屬性時(shí),可經(jīng)過(guò)平衡考慮選用存儲(chǔ)過(guò)程。//目前都是杜絕使用存儲(chǔ)過(guò)程的,我覺(jué)得用起來(lái)比較方便,對(duì)于我們來(lái)說(shuō),主要原因是會(huì)給DBA帶來(lái)管理方面的麻煩, //因?yàn)闀r(shí)間一長(zhǎng),存儲(chǔ)過(guò)程的邏輯和使用場(chǎng)景,往往沒(méi)人能了解,容易產(chǎn)生更多問(wèn)題10.當(dāng)處理表間的關(guān)聯(lián)約束所付出的代價(jià)(常常是使用性上的代價(jià))超過(guò)了保證不會(huì)出現(xiàn)修改、刪除、更改異常所付出的代價(jià),并且數(shù)據(jù)冗余也不是主要的問(wèn)題時(shí),表設(shè)計(jì)可以不符合四個(gè)范式。四個(gè)范式確保了不會(huì)出現(xiàn)異常,但也可能由此導(dǎo)致過(guò)于純潔的設(shè)計(jì),使得表結(jié)構(gòu)難于使用,所以在設(shè)計(jì)時(shí)需要進(jìn)行綜合判斷,但首先確保符合四個(gè)范式,然后再進(jìn)行精化修正是剛剛進(jìn)入數(shù)據(jù)庫(kù)設(shè)計(jì)領(lǐng)域時(shí)可以采用的最好辦法。11.設(shè)計(jì)出的表要具有較好的使用性,主要體現(xiàn)在查詢時(shí)是否需要關(guān)聯(lián)多張表且還需使用復(fù)雜的SQL技巧。我感覺(jué)遵守的范式越多,就越使SQL復(fù)雜,具體情況具體分析。設(shè)計(jì)出的表要盡可能減少數(shù)據(jù)冗余,確保數(shù)據(jù)的準(zhǔn)確性,有效的控制冗余有助于提高數(shù)據(jù)庫(kù)的性能因此,考慮了以上條件之后,表設(shè)計(jì)約定規(guī)則如下:復(fù)制代碼 //規(guī)則1:表必須要有主鍵。 //規(guī)則2:一個(gè)字段只表示一個(gè)含義。 //規(guī)則3:總是包含兩個(gè)日期字段:gmt_create(創(chuàng)建日期),gmt_modified(修改日期),且這兩個(gè)字段不應(yīng)該包含有額外的業(yè)務(wù)邏輯。 //規(guī)則4:MySQL中,gmt_create、gmt_modified使用DATETIME類型。 //規(guī)則5:禁止使用復(fù)雜數(shù)據(jù)類型(數(shù)組,自定義類型等)。 //規(guī)則6: MySQL中,附屬表拆分后,附屬表id與主表id保持一致。不允許在附屬表新增主鍵字段。 //規(guī)則7: MySQL中,存在過(guò)期概念的表,在其設(shè)計(jì)之初就必須有過(guò)期機(jī)制,且有明確的過(guò)期時(shí)間。過(guò)期數(shù)據(jù)必須遷移至歷史表中。 //規(guī)則8: MySQL中,不再使用的表,必須通知DBA予以更名歸檔。 //規(guī)則9: MySQL中,線上表中若有不再使用的字段,為保證數(shù)據(jù)完整,禁止刪除。 //規(guī)則10: MySQL中,禁止使用OCI驅(qū)動(dòng),全部使用THI驅(qū)動(dòng)。 復(fù)制代碼 關(guān)于MySQL的部分學(xué)習(xí)筆記總結(jié):一、事務(wù)跟存儲(chǔ)引擎1.四種事務(wù)隔離級(jí)別:read uncommited, read commited(大多數(shù)db默認(rèn)的),repeatable read(mysql默認(rèn)), seriazable。2.mysql是默認(rèn)的auto commited, 也就是說(shuō)每次查詢默認(rèn)都是自動(dòng)提交的(show variables like 'autocommited')。mysql可以通過(guò)set transaction isolatioin level命令來(lái)設(shè)置隔離級(jí)別,例如:set session transaction isolation level read commited。3.mysql中像innodb采用mvcc(多版本并發(fā)控制)來(lái)處理并發(fā)。mvcc只工作在read commited,repeatable read這兩種事務(wù)隔離級(jí)別上。read uncommited隔離級(jí)別不兼容mvcc是因?yàn)樵谠摷?jí)別得下的查詢,不讀取符合當(dāng)前事務(wù)版本的數(shù)據(jù)行,而是最新版本的數(shù)據(jù)行。seriazable隔離級(jí)別不兼容MVCC,因?yàn)樵摷?jí)別下的讀操作會(huì)對(duì)每個(gè)返回行進(jìn)行加鎖。4.選擇存儲(chǔ)引擎,并發(fā)選用myisam,事務(wù)選擇innodb,myisam比innodb更容易出錯(cuò),出錯(cuò)了恢復(fù)的時(shí)間也比較長(zhǎng)。只有myisam支持全文檢索。5.把表從一種存儲(chǔ)引擎轉(zhuǎn)到另一種引擎:// 1. alter table mytable engine=falcon; 操作費(fèi)時(shí),可能會(huì)占用服務(wù)器的所有i/o處理能力。 // 2. create table innodb_table like myisam_table; // alter table innodb_table engine=innodb; // insert into innodb_table select * from myisam_table; 二、數(shù)據(jù)類型1.盡可能的要把field定義為Not NULL, mysql比較難優(yōu)化使用了可空列的查詢,它會(huì)使索引,索引統(tǒng)計(jì)更加復(fù)雜??煽樟行枰嗟拇鎯?chǔ)空間,還需要mysql內(nèi)部進(jìn)行特殊處理,當(dāng)可空列被索引時(shí),每條記錄都需要一個(gè)格外的字節(jié)。 即使要在表中存儲(chǔ)"沒(méi)有值"的字段,考慮使用0,特殊字段或者空字符串來(lái)代替。2.datetime與timestamp能保存同樣的數(shù)據(jù):精確度為秒,但是timestamp使用的空間只有datetime的一半,還能保存時(shí)區(qū),擁有特殊的自動(dòng)更新能力。但是timestamp保存的時(shí)間范圍要比datetime要小得多。mysql能存儲(chǔ)的最細(xì)的時(shí)間粒度為秒3.mysql支持很多種別名,如bool,integer,nummeric.4.float與double類型支持使用標(biāo)準(zhǔn)的浮點(diǎn)運(yùn)算進(jìn)行近似計(jì)算。 Decimal類型保存精確的小數(shù),在>=mysql5.0,mysql服務(wù)器自身進(jìn)行了decimal的運(yùn)算,因?yàn)镃PU不支持直接對(duì)它進(jìn)行運(yùn)算,所以慢一點(diǎn)。5.mysql會(huì)把text與blob類型的列當(dāng)成有實(shí)體的對(duì)象來(lái)進(jìn)行保存。他們有各自的數(shù)據(jù)類型家族(tinytext,smalltext,text,mediumtext,longtext; blob類似); mysql對(duì)blob與text列排序方式和其他類型有所不同,它不會(huì)按照字符串的完整長(zhǎng)度來(lái)排序。而只是按照max_sort_length規(guī)定的若干個(gè)字節(jié)來(lái)進(jìn)行排序。6.采用enum來(lái)代替字符串類型。mysql在內(nèi)部把每個(gè)枚舉值都保存為整數(shù)。enum在內(nèi)部是按照數(shù)字進(jìn)行排序的,而不是按照字符串。enum最不好的就是字符串列表是固定的,添加和刪除必須使用alter table。7.ip地址,一般會(huì)采用varchar(15)列來(lái)保存。事實(shí)上,IP地址是個(gè)無(wú)符號(hào)的32位整數(shù),而不是字符串。mysql提供了inet_aton()和inet_nota()函數(shù)在證書與ip地址之間進(jìn)行轉(zhuǎn)換。三、索引1.聚集索引不僅僅是一種單獨(dú)的索引類型,而且是一種存儲(chǔ)數(shù)據(jù)的方式。Innodb引擎的聚集索引實(shí)際上在同樣的結(jié)構(gòu)中保存了B-Tree索引和數(shù)據(jù)行。當(dāng)表有聚集索引時(shí),它的數(shù)據(jù)行實(shí)際上保存在索引的葉子上。注意是存儲(chǔ)引擎來(lái)實(shí)現(xiàn)索引。2.myisam與innodb數(shù)據(jù)布局:myisam索引樹(shù)(無(wú)論是主鍵索引還是非主鍵索引)葉子節(jié)點(diǎn)都是指向的數(shù)據(jù)行,而innodb中聚集索引,主鍵索引樹(shù)葉子節(jié)點(diǎn)就帶得有數(shù)據(jù)的內(nèi)容,而非主鍵索引樹(shù)中葉子節(jié)點(diǎn)指向主鍵值,而不是數(shù)據(jù)的位置。3.mysql有兩種產(chǎn)生排序結(jié)果的方式:使用文件排序,或者掃描有序的索引。目前只有myisam支持全文索引。4.myisam表有表級(jí)鎖;myisam表不支持事務(wù),實(shí)際上,myisam并不保證單條命令完成;myisam只緩存了mysql進(jìn)程內(nèi)部的索引,并保存在鍵緩存區(qū)內(nèi)。OS緩存了表的數(shù)據(jù);行被緊密的保存在一起,磁盤上的數(shù)據(jù)有很小的磁盤占用和快速的全表掃描。5.innodb支持事務(wù)和四種事務(wù)隔離級(jí)別;在mysql5.0中,只有innodb支持外鍵;支持行級(jí)鎖與mvcc;所有的innodb表都是按照主鍵聚集的;所有索引(出開(kāi)主鍵)都是按主鍵引用行;索引沒(méi)有使用前綴壓縮,因此索引可能比myisam大很多;數(shù)據(jù)轉(zhuǎn)載緩慢;阻塞auto_increment,也就是用表級(jí)鎖來(lái)產(chǎn)生每個(gè)auto_increment。四、MYSQL性能分析1.mysql提供了一個(gè)benchmark(int 循環(huán)次數(shù),char* 表達(dá)式); 可以分析表達(dá)式執(zhí)行所花時(shí)間。 例如:// select BENCHMARK(10000,SHA1('aaaaaaaaaaaaaaaa'))2.mysql有兩種查詢?nèi)罩?#xff1a;普通日志和慢速日志。五、MYSQL高級(jí)特性1.在mysql中,只有myisam存儲(chǔ)引擎支持全文索引。myisam全文索引是一種特殊的具有兩層結(jié)構(gòu)的B樹(shù)。2.存儲(chǔ)引擎事務(wù)在存儲(chǔ)引擎內(nèi)部被賦予acid屬性,分布式(XA)是一種高層次事務(wù),它可以歷喲內(nèi)部個(gè)兩段提交的方式將acid屬性擴(kuò)展到存儲(chǔ)引擎外部,甚至數(shù)據(jù)庫(kù)外部。階段1:通知所有提交者準(zhǔn)備提交 階段2:通知所有參與者進(jìn)行真正提交。3.mysql 的字符集和校對(duì)規(guī)則有 4 個(gè)級(jí)別的默認(rèn)設(shè)置:服務(wù)器級(jí)、數(shù)據(jù)庫(kù)級(jí)、表級(jí)和字段級(jí)。Mysql4.1 開(kāi)始支持 SQL 的子查詢。復(fù)制代碼 /******************************************/ /* 數(shù)據(jù)庫(kù)全名 = degopen@10.218.249.92:3318【mysql】 */ /* 表名稱 = task_new */ /******************************************/ CREATE TABLE `task_new` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',`task_name` varchar(128) NOT NULL COMMENT '任務(wù)名稱',`image` varchar(128) DEFAULT NULL COMMENT '任務(wù)圖標(biāo)',`description` varchar(1024) NOT NULL COMMENT '任務(wù)描述',`content` varchar(1024) NOT NULL COMMENT '任務(wù)內(nèi)容',`finished_message` varchar(128) DEFAULT NULL COMMENT '任務(wù)完成提示信息',`task_scope` int(11) NOT NULL COMMENT '任務(wù)范圍, 0-平臺(tái)任務(wù), 1-游戲任務(wù)',`series_task` int(11) NOT NULL DEFAULT '0' COMMENT '任務(wù)類型: 系列任務(wù),單獨(dú)任務(wù)',`task_type` int(11) NOT NULL DEFAULT '0' COMMENT '任務(wù)類型: 固定任務(wù), 推廣任務(wù), 日常任務(wù)',`pre_task` varchar(128) DEFAULT NULL COMMENT '前置任務(wù)',`post_task` varchar(128) DEFAULT NULL COMMENT '后置任務(wù)',`task_status` int(11) NOT NULL COMMENT '任務(wù)狀態(tài), 待審核、未開(kāi)始、生效中、已暫停、已完成、審核未通過(guò)',`auto_task` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否手動(dòng)任務(wù), 0-否, 1-是',`is_required` tinyint(4) NOT NULL COMMENT '是否必須任務(wù)',`event_type` varchar(64) DEFAULT NULL COMMENT '關(guān)心的事件類型',`task_target` bigint(20) DEFAULT '0' COMMENT '任務(wù)目標(biāo)',`reset_num` int(11) NOT NULL COMMENT '重置次數(shù)',`reset_cycle` int(11) NOT NULL COMMENT '重置周期',`task_interval` int(11) NOT NULL COMMENT '任務(wù)間隔',`xiaoer` bigint(20) unsigned NOT NULL COMMENT '創(chuàng)建人',`review_id` bigint(20) unsigned NOT NULL COMMENT '審核人ID',`last_start_time` datetime DEFAULT NULL COMMENT '上次生效時(shí)間',`gmt_create` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間',`gmt_modified` datetime NOT NULL COMMENT '修改時(shí)間',`start_time` datetime NOT NULL COMMENT '開(kāi)始時(shí)間',`end_time` datetime NOT NULL COMMENT '結(jié)束時(shí)間',`start_condition` varchar(1024) NOT NULL COMMENT '任務(wù)觸發(fā)條件',`end_condition` varchar(1024) NOT NULL COMMENT '任務(wù)完成條件',`enable` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否可用',`rule` varchar(4096) NOT NULL COMMENT '任務(wù)規(guī)則',`priority` int(11) NOT NULL DEFAULT '1' COMMENT '任務(wù)優(yōu)先級(jí)',`progress_rule` varchar(2048) NOT NULL DEFAULT '' COMMENT '進(jìn)度計(jì)算規(guī)則',`order_no` int(11) DEFAULT '1' COMMENT '排序號(hào)',`classification` int(11) DEFAULT '0' COMMENT '0:默認(rèn)分類\n1:玩游戲\n2:抽獎(jiǎng)',`level` int(11) DEFAULT '0' COMMENT '針對(duì)同一個(gè)分類,不同的等級(jí)',`ext1` longtext COMMENT '擴(kuò)展字段1(UU中使用該字段指示按鈕跳轉(zhuǎn))',`ext2` longtext COMMENT '擴(kuò)展字段2,暫時(shí)預(yù)留',`channel` int(11) DEFAULT '0' COMMENT '任務(wù)渠道:0-uu或者1-game_box',`consecutive_day` int(11) DEFAULT '1' COMMENT '連續(xù)完成任務(wù)的天數(shù)',`activity` varchar(256) DEFAULT 'default' COMMENT '任務(wù)所屬的活動(dòng)名字',`device` text COMMENT '機(jī)型',`packages` text COMMENT '應(yīng)用',PRIMARY KEY (`id`),KEY `name_channel` (`task_name`,`channel`),KEY `activity` (`activity`(255)) ) ENGINE=InnoDB AUTO_INCREMENT=1194 DEFAULT CHARSET=utf8 COMMENT='任務(wù)表'; --------------------------------------------------------------------------------------- 數(shù)據(jù)庫(kù)表設(shè)計(jì)總結(jié) 一、實(shí)體與表對(duì)應(yīng)關(guān)系表<=>實(shí)體,字段<=>屬性。二、表與表的關(guān)系(實(shí)體間的關(guān)系):一對(duì)一、一對(duì)多、多對(duì)多一對(duì)一:一條記錄只對(duì)應(yīng)其他表中的一條記錄有關(guān)系學(xué)生基本信息表t_student,成績(jī)表t_studentScore含有一個(gè)外鍵studentId?;拘畔⒈碇械膕tudentId和成績(jī)表中的studentId就是一對(duì)一的關(guān)系。一對(duì)多:A表一條記錄對(duì)應(yīng)B表中多條記錄有關(guān)系,B表的記錄不被A表記錄共享(有關(guān)系)。班級(jí)表和學(xué)生表,一個(gè)班級(jí)有多個(gè)學(xué)生,對(duì)班級(jí)來(lái)說(shuō)就是一對(duì)多的關(guān)系。多對(duì)多:A表一條記錄和B表多條記錄有關(guān)系,B表的一條記錄也和A表的多條記錄有關(guān)系(互相共享)。學(xué)生表和科目表,學(xué)生可以選擇多個(gè)科目,每個(gè)科目可以被多個(gè)學(xué)生選擇。三、基本表的完整性(1)原子性。字段是不可再分解的。 (2)原始性。記錄是原始數(shù)據(jù)(基礎(chǔ)數(shù)據(jù))的記錄。 (3)穩(wěn)定性。結(jié)構(gòu)是相對(duì)穩(wěn)定的,表中的記錄是要長(zhǎng)期保存的。 (4)演繹性。由基本表與代碼表中的數(shù)據(jù),可以派生出所有的輸出數(shù)據(jù)。四、其他常用表1.中間表中間表是針對(duì)多對(duì)多關(guān)系的。就比如做公交查詢系統(tǒng),里面有兩個(gè)表,分別是車站表t_busstation、線路表t_road,根據(jù)常識(shí),一個(gè)站有多個(gè)線路經(jīng)過(guò),而每個(gè)線路又有多個(gè)車站,怎么才能將兩個(gè)表聯(lián)系起來(lái)呢,如果是一對(duì)一,一對(duì)多,我們一個(gè)表, 兩個(gè)表就可以將他們實(shí)現(xiàn)了。但是多對(duì)多呢,這樣我們就必須借助中間表用來(lái)連接兩個(gè)表。一般中間表只有一個(gè)自增主鍵+兩個(gè)表的主鍵。中間表是沒(méi)有屬性的因?yàn)樗皇且粋€(gè)基本表。2.臨時(shí)表臨時(shí)表是那些以#號(hào)開(kāi)頭為名字的數(shù)據(jù)表,它主要是用來(lái)存放臨時(shí)數(shù)據(jù)的,當(dāng)用戶斷開(kāi)連接但沒(méi)有清除臨時(shí)表里的數(shù)據(jù)時(shí),系統(tǒng)會(huì)自動(dòng)把臨時(shí)表里的數(shù)據(jù)清空。臨時(shí)表是放在系統(tǒng)數(shù)據(jù)庫(kù) tempdb中的,而不是當(dāng)前數(shù)據(jù)庫(kù)。臨時(shí)表分兩種:本地臨時(shí)表和全局臨時(shí)表。a.本地臨時(shí)表本地臨時(shí)表是以#開(kāi)頭的,只對(duì)當(dāng)前的數(shù)據(jù)庫(kù)用戶可見(jiàn),而其他的用戶是不可見(jiàn)的。當(dāng)數(shù)據(jù)庫(kù)實(shí)例斷開(kāi)后當(dāng)然也就丟失了數(shù)據(jù)了,不管是顯式清空還是系統(tǒng)回收。 b.全局臨時(shí)表以“##”開(kāi)頭的,而且是對(duì)所有的用戶都是可見(jiàn),當(dāng)你斷開(kāi)數(shù)據(jù)庫(kù)實(shí)例連接時(shí),只要還有別的系統(tǒng)項(xiàng)目在引用它,連著數(shù)據(jù)庫(kù),那么數(shù)據(jù)就存在,只有當(dāng)別的系統(tǒng)也全部斷開(kāi)連接時(shí),系統(tǒng)才會(huì)清除全局臨時(shí)表的數(shù)據(jù)。建立臨時(shí)表的語(yǔ)句:復(fù)制代碼本地臨時(shí)表:create table #student (studentID int ,studentName nvarchar (40),classID int) 復(fù)制代碼 復(fù)制代碼全局臨時(shí)表:create table ##student (studentID int ,studentName nvarchar (40).classID int) 復(fù)制代碼 也可以用SQL語(yǔ)句完成:select * from employee into #student五、三大范式第一范式:如果每列(或者每個(gè)屬性)都是不可再分的最小數(shù)據(jù)單元(也稱為最小的原子單元),則滿足第一范式.比如一個(gè)工人的基本信息表,里面有工人的工號(hào),性別,年齡,這些屬性都是不可分割的,所以這個(gè)表就符合了第一范式。第二范式: 就是在第一范式的基礎(chǔ)上延伸,使之表里的每個(gè)字段都與主鍵發(fā)生關(guān)系。假如一個(gè)關(guān)系滿足第一范式,并且除了主鍵以外的其它字段,都依賴于該主鍵,則滿足第二范式. 例如:訂單表(訂單編號(hào)、產(chǎn)品編號(hào)、定購(gòu)日期、價(jià)格、……),"訂單編號(hào)"為主鍵,"產(chǎn)品編號(hào)"和主鍵列沒(méi)有直接的關(guān)系,即"產(chǎn)品編號(hào)"列不依賴于主鍵列,這個(gè)列我們就可以把它刪除。第三范式:在第二范式的基礎(chǔ)上更進(jìn)一步,也就是為了實(shí)現(xiàn)表里的列都與主鍵列直接相關(guān),不是間接相關(guān)。這個(gè)我們可以用“Armstrong 公理”中的傳遞規(guī)則來(lái)推理。定義: 設(shè)U是關(guān)系模式R 的屬性集,F 是R 上成立的只涉及U 中屬性的函數(shù)依賴集。若X→Y 和 Y→Z在R 上成立,則X →Z 在R 上成立。因此我們就來(lái)看在網(wǎng)上搜索到的例子:例如:訂單表(訂單編號(hào),定購(gòu)日期,顧客編號(hào),顧客姓名,……),初看該表沒(méi)有問(wèn)題,滿足第二范式,每列都和主鍵列"訂單編號(hào)"相關(guān),再細(xì)看你會(huì)發(fā)現(xiàn)"顧客姓名"和"顧客編號(hào)"相關(guān),"顧客編號(hào)"和"訂單編號(hào)"又相關(guān),最后經(jīng)過(guò)傳遞依賴,"顧客姓名"也和"訂單編號(hào)"相關(guān)。為了滿足第三范式,應(yīng)去掉"顧客姓名"列,放入客戶表中。這里其實(shí)就是為了說(shuō)明數(shù)據(jù)庫(kù)的表里步要出現(xiàn)冗余,在顧客表里已經(jīng)有了"顧客姓名"了,而在訂單表里就別出現(xiàn)了,而直接根據(jù)顧客編號(hào)相關(guān)聯(lián)就可以,否則造成資源浪費(fèi)。三大范式延伸:第一范式:1NF是對(duì)屬性的原子性約束,要求屬性具有原子性,不可再分解; 第二范式:2NF是對(duì)記錄的惟一性約束,要求記錄有惟一標(biāo)識(shí),即實(shí)體的惟一性; 第三范式:3NF是對(duì)字段冗余性的約束,即任何字段不能由其他字段派生出來(lái),它要求字段沒(méi)有冗余。其實(shí)在設(shè)計(jì)數(shù)據(jù)庫(kù)的時(shí)候我們最多的要遵循的就是第三范式,但是并不是越滿足第三范式數(shù)據(jù)庫(kù)就設(shè)計(jì)的越完美,這種錯(cuò)誤是錯(cuò)誤的。有時(shí)候增加點(diǎn)冗余相反的會(huì)提高訪問(wèn)速率,因此在實(shí)際的設(shè)計(jì)過(guò)程中應(yīng)降低對(duì)范式的要求。以前對(duì)數(shù)據(jù)冗余并不是很了解,在百度知道里的定義是這樣的:在一個(gè)數(shù)據(jù)集合中重復(fù)的數(shù)據(jù)稱為數(shù)據(jù)冗余. 但是不是說(shuō)我們表的主鍵在其他表里重復(fù)出現(xiàn)就是冗余,這不是,而是為了連接兩個(gè)表。只有非鍵字段就是既不是主鍵外鍵等約束的鍵如果重復(fù)出現(xiàn),就會(huì)形成數(shù)據(jù)冗余。數(shù)據(jù)冗余也包括重復(fù)性冗余和派生冗余。比如工人表里有"基本工資","獎(jiǎng)金"兩列,然后還有一個(gè)"總工資"的列,這個(gè)總工資就是派生冗余。低級(jí)的重復(fù)性冗余一定要避免,杜絕,但是像派生冗余還是提倡的因?yàn)樗芴岣咴L問(wèn)的效率。個(gè)人總結(jié):事物的屬性對(duì)應(yīng)表的屬性,將一張表看作一個(gè)事物。如,書的屬性有價(jià)格、重量、等等。(一般表都有Id來(lái)區(qū)分每條記錄) ----------------------------------------------------------------------------

數(shù)據(jù)庫(kù)分層

數(shù)據(jù)倉(cāng)庫(kù)分層的原因1通過(guò)數(shù)據(jù)預(yù)處理提高效率,因?yàn)轭A(yù)處理,所以會(huì)存在冗余數(shù)據(jù)2如果不分層而業(yè)務(wù)系統(tǒng)的業(yè)務(wù)規(guī)則發(fā)生變化,就會(huì)影響整個(gè)數(shù)據(jù)清洗過(guò)程,工作量巨大3通過(guò)分層管理來(lái)實(shí)現(xiàn)分步完成工作,這樣每一層的處理邏輯就簡(jiǎn)單了標(biāo)準(zhǔn)的數(shù)據(jù)倉(cāng)庫(kù)分層:ods(臨時(shí)存儲(chǔ)層),pdw(數(shù)據(jù)倉(cāng)庫(kù)層),mid(數(shù)據(jù)集市層),app(應(yīng)用層)ods:歷史存儲(chǔ)層,它和源系統(tǒng)數(shù)據(jù)是同構(gòu)的,而且這一層數(shù)據(jù)粒度是最細(xì)的,這層的表分為兩種,一種是存儲(chǔ)當(dāng)前需要加載的數(shù)據(jù),一種是用于存儲(chǔ)處理完后的數(shù)據(jù)。pdw:數(shù)據(jù)倉(cāng)庫(kù)層,它的數(shù)據(jù)是干凈的數(shù)據(jù),是一致的準(zhǔn)確的,也就是清洗后的數(shù)據(jù),它的數(shù)據(jù)一般都遵循數(shù)據(jù)庫(kù)第三范式,數(shù)據(jù)粒度和ods的粒度相同,它會(huì)保存bi系統(tǒng)中所有歷史數(shù)據(jù)mid:數(shù)據(jù)集市層,它是面向主題組織數(shù)據(jù)的,通常是星狀和雪花狀數(shù)據(jù),從數(shù)據(jù)粒度將,它是輕度匯總級(jí)別的數(shù)據(jù),已經(jīng)不存在明細(xì)的數(shù)據(jù)了,從廣度來(lái)說(shuō),它包含了所有業(yè)務(wù)數(shù)量。從分析角度講,大概就是近幾年app:應(yīng)用層,數(shù)據(jù)粒度高度匯總,倒不一定涵蓋所有業(yè)務(wù)數(shù)據(jù),只是mid層數(shù)據(jù)的一個(gè)子集。數(shù)據(jù)倉(cāng)庫(kù)的目的是構(gòu)建面向分析的集成化數(shù)據(jù)環(huán)境,為企業(yè)提供決策支持。數(shù)據(jù)倉(cāng)庫(kù)的context也可以理解為:數(shù)據(jù)源,數(shù)據(jù)倉(cāng)庫(kù),數(shù)據(jù)應(yīng)用數(shù)據(jù)倉(cāng)庫(kù)可以理解為中間集成化數(shù)據(jù)管理的一個(gè)平臺(tái)etl(抽取extra,轉(zhuǎn)化transfer,裝載load)是數(shù)據(jù)倉(cāng)庫(kù)的流水線,也可以認(rèn)為是數(shù)據(jù)倉(cāng)庫(kù)的血液。數(shù)據(jù)倉(cāng)庫(kù)的存儲(chǔ)并不需要存儲(chǔ)所有原始數(shù)據(jù),因?yàn)楸热缒愦鎯?chǔ)冗長(zhǎng)的文本數(shù)據(jù)完全沒(méi)必要,但需要存儲(chǔ)細(xì)節(jié)數(shù)據(jù),因?yàn)樾枨笫嵌嘧兊?#xff0c;而且數(shù)據(jù)倉(cāng)庫(kù)是導(dǎo)入數(shù)據(jù)必須經(jīng)過(guò)整理和轉(zhuǎn)換使它面向主題,因?yàn)榍芭_(tái)數(shù)據(jù)庫(kù)的數(shù)據(jù)是基于oltp操作組織優(yōu)化的,這些可能不適合做分析,面向主題的組織形式才有利于分析。多維數(shù)據(jù)模型就是說(shuō)可以多維度交叉查詢和細(xì)分,應(yīng)用一般都是基于聯(lián)機(jī)分析處理(online analytical process OLAP),面向特定需求群體的數(shù)據(jù)集市會(huì)基于多位數(shù)據(jù)模型構(gòu)建而報(bào)表展示就是將聚合數(shù)據(jù)和多維分析數(shù)據(jù)展示到報(bào)表,提供簡(jiǎn)單和直觀的數(shù)據(jù)。元數(shù)據(jù),也叫解釋性數(shù)據(jù),或者數(shù)據(jù)字典,會(huì)記錄數(shù)據(jù)倉(cāng)庫(kù)中模型的定義,各層級(jí)之間的映射關(guān)系,監(jiān)控?cái)?shù)據(jù)倉(cāng)庫(kù)的數(shù)據(jù)狀態(tài)和etl的任務(wù)運(yùn)行狀態(tài)。一般通過(guò)元數(shù)據(jù)資料庫(kù)來(lái)統(tǒng)一存儲(chǔ)和管理元數(shù)據(jù)。------------------------------------------------------------------------------ -基本查詢 select id,c_mmcode,c_mmroomname,c_parentId from s_mmroom; --層次化查詢 select id,c_mmcode,c_mmroomname,c_parentId from s_mmroom start with c_parentId='0' connect by prior id = c_parentId; --使用level節(jié)點(diǎn) select level,id,c_mmcode,c_mmroomname,c_parentId from s_mmroom start with c_parentId='0' connect by prior id = c_parentId; --查詢層次數(shù) select count(distinct level) from s_mmroom start with c_parentId='0' connect by prior id = c_parentId; ---查詢結(jié)果的層次化 select level,LPAD(' ',2*LEVEL-1)||' '||c_mmcode||' '||c_mmroomname,c_parentId from s_mmroom start with c_parentId='0' connect by prior id = c_parentId; --從非根節(jié)點(diǎn)開(kāi)始遍歷 select level,LPAD(' ',2*LEVEL-1)||' '||c_mmcode||' '||c_mmroomname,c_parentId from s_mmroom start with c_parentId='00000000000000000000000000000000' connect by prior id = c_parentId; --在START WITH中使用子查詢? 下面這個(gè)查詢使用子查詢來(lái)選擇指定節(jié)點(diǎn)的。然后傳給START WITH子句。 select level,lpad(' ',2*level-1)||' '||c_mmroomname from s_mmroom start with c_parentId=(select id from s_mmroom where c_mmroomname like '%中國(guó)船級(jí)社%') connect by prior id =c_parentId; --從下向上遍歷樹(shù)? 不一定非要按照從父節(jié)點(diǎn)到子節(jié)點(diǎn)的順序從上至下遍歷樹(shù);也可以從某個(gè)子節(jié)點(diǎn)開(kāi)始,從下而上遍歷。實(shí)現(xiàn)的方法是交換父節(jié)點(diǎn)和子節(jié)點(diǎn)在CONNECT BY PRIOR子句中的順序 select level,lpad(' ',2*level-1)||' '||c_mmroomname from s_mmroom start with c_parentId='00000000000000000000000000000000' connect by prior id = c_parentId; --從層次化查詢中刪除節(jié)點(diǎn)和分支?? 略 表名后面加where --在層次化查詢中加入其它條件????? 略 表名后面加where ------------------------------------------------------------------ BLOCK(塊)block 是oracle中最小的分配單位,也是最小的I/O單位,可以在創(chuàng)建數(shù)據(jù)庫(kù)時(shí)設(shè)定block的大小,可以設(shè)為任意的大小,但為了支持與兼容方面,建議現(xiàn)實(shí)中設(shè)為2的冪,例如:2KB、4KB、8KB,最大為32KB。EXTENT(區(qū))extent 是由邏輯連續(xù)的block組成的,注意是邏輯上的,一般來(lái)講,文件本身在磁盤上不是連續(xù)的,extent的大小可能是一個(gè)block的大小,也可能大到2GB,SEGMENT(段)segment 是由一個(gè)或多個(gè)extent組成的,segment就是占用存儲(chǔ)空間的數(shù)據(jù)庫(kù)對(duì)象,例如表、索引等,segment在tablespace中,但可以包含這個(gè)tablespace中的多個(gè)數(shù)據(jù)文件中的數(shù)據(jù)TABLESPACE(表空間)ORACLE數(shù)據(jù)庫(kù)是由一個(gè)或多個(gè)TABLESPACE構(gòu)成,什么是TABLESPACE? 一種邏輯上的存儲(chǔ)容器,包括一個(gè)或多個(gè)datafile(數(shù)據(jù)文件)。tablespace可以包含多個(gè)segment(表段,索引段等),但一個(gè)segment只能屬于一個(gè)tablespace。上圖中圓柱形代表datafile(user_data01.db和user_data02.dbf),T1,T2,I1是3個(gè)segment(可能是2個(gè)表和1個(gè)索引),這個(gè)USER_DATA ?TABLESPACE分配了4個(gè)extent,T1和I1各有一個(gè)extent。如果這個(gè)TABLESPACE需要更多的空間,可以調(diào)整已分配給該TABLESPACE的datafile的大小,也可以增加第三個(gè)datafile。要說(shuō)明的是上述所討論的概念除了block都是邏輯上的概念,所謂連續(xù)的也是邏輯上連續(xù)的。 -------------------------------------------------------------------------------

myslq水平拆分

mysql的水平拆分和垂直拆分 1,水平分割:例:QQ的登錄表。假設(shè)QQ的用戶有100億,如果只有一張表,每個(gè)用戶登錄的時(shí)候數(shù)據(jù)庫(kù)都要從這100億中查找,會(huì)很慢很慢。如果將這一張表分成100份,每張表有1億條,就小了很多,比如qq0,qq1,qq1...qq99表。用戶登錄的時(shí)候,可以將用戶的id%100,那么會(huì)得到0-99的數(shù),查詢表的時(shí)候,將表名qq跟取模的數(shù)連接起來(lái),就構(gòu)建了表名。比如123456789用戶,取模的89,那么就到qq89表查詢,查詢的時(shí)間將會(huì)大大縮短。這就是水平分割。2,垂直分割:垂直分割指的是:表的記錄并不多,但是字段卻很長(zhǎng),表占用空間很大,檢索表的時(shí)候需要執(zhí)行大量的IO,嚴(yán)重降低了性能。這時(shí)需要把大的字段拆分到另一個(gè)表,并且該表與原表是一對(duì)一的關(guān)系。例如學(xué)生答題表tt:有如下字段:Id name 分?jǐn)?shù) 題目 回答其中題目和回答是比較大的字段,id name 分?jǐn)?shù)比較小。如果我們只想查詢id為8的學(xué)生的分?jǐn)?shù):select 分?jǐn)?shù) from tt where id = 8;雖然知識(shí)查詢分?jǐn)?shù),但是題目和回答這兩個(gè)大字段也是要被掃描的,很消耗性能。但是我們只關(guān)心分?jǐn)?shù),并不想查詢題目和回答。這就可以使用垂直分割。我們可以把題目單獨(dú)放到一張表中,通過(guò)id與tt表建立一對(duì)一的關(guān)系,同樣將回答單獨(dú)放到一張表中。這樣我們插敘tt中的分?jǐn)?shù)的時(shí)候就不會(huì)掃描題目和回答了。3,其他要點(diǎn):1)存放圖片、文件等大文件用文件系統(tǒng)存儲(chǔ)。數(shù)據(jù)庫(kù)只存儲(chǔ)路徑,圖片和文件存放在文件系統(tǒng),甚至單獨(dú)存放在一臺(tái)服務(wù)器(圖床)。2)數(shù)據(jù)參數(shù)配置。最重要的參數(shù)就是內(nèi)存,我們主要用的innodb引擎,所以下面兩個(gè)參數(shù)調(diào)的很大:innodb_additional_mem_pool_size=64Minnodb_buffer_pool_size=1G對(duì)于MyISAM,需要調(diào)整key_buffer_size,當(dāng)然調(diào)整參數(shù)還是要看狀態(tài),用show status語(yǔ)句可以看到當(dāng)前狀態(tài),以決定該調(diào)整哪些參數(shù)。4,合理的硬件資源和操作系統(tǒng)如果機(jī)器的內(nèi)存超過(guò)4G,那么應(yīng)當(dāng)采用64位操作系統(tǒng)和64位MySQL。案例:簡(jiǎn)單購(gòu)物系統(tǒng)暫設(shè)涉及如下表:1.產(chǎn)品表(數(shù)據(jù)量10w,穩(wěn)定)2.訂單表(數(shù)據(jù)量200w,且有增長(zhǎng)趨勢(shì))3.用戶表 (數(shù)據(jù)量100w,且有增長(zhǎng)趨勢(shì))以mysql為例講述下水平拆分和垂直拆分,mysql能容忍的數(shù)量級(jí)在百萬(wàn)靜態(tài)數(shù)據(jù)可以到千萬(wàn)垂直拆分:解決問(wèn)題:表與表之間的io競(jìng)爭(zhēng)不解決問(wèn)題:單表中數(shù)據(jù)量增長(zhǎng)出現(xiàn)的壓力方案:把產(chǎn)品表和用戶表放到一個(gè)server上訂單表單獨(dú)放到一個(gè)server上水平拆分:解決問(wèn)題:單表中數(shù)據(jù)量增長(zhǎng)出現(xiàn)的壓力不解決問(wèn)題:表與表之間的io爭(zhēng)奪方案:用戶表通過(guò)性別拆分為男用戶表和女用戶表訂單表通過(guò)已完成和完成中拆分為已完成訂單和未完成訂單產(chǎn)品表 未完成訂單放一個(gè)server上已完成訂單表盒男用戶表放一個(gè)server上女用戶表放一個(gè)server上 ----------------------------------------------------------------------------- 目前很多互聯(lián)網(wǎng)系統(tǒng)都存在單表數(shù)據(jù)量過(guò)大的問(wèn)題,這就降低了查詢速度,影響了客戶體驗(yàn)。為了提高查詢速度,我們可以優(yōu)化sql語(yǔ)句,優(yōu)化表結(jié)構(gòu)和索引,不過(guò)對(duì)那些百萬(wàn)級(jí)千萬(wàn)級(jí)的數(shù)據(jù)庫(kù)表,即便是優(yōu)化過(guò)后,查詢速度還是滿足不了要求。這時(shí)候我們就可以通過(guò)分表降低單次查詢數(shù)據(jù)量,從而提高查詢速度,一般分表的方式有兩種:水平拆分和垂直拆分,兩者各有利弊,適用于不同的情況。水平拆分 水平拆分是指數(shù)據(jù)表行的拆分,表的行數(shù)超過(guò)200萬(wàn)行時(shí),就會(huì)變慢,這時(shí)可以把一張的表的數(shù)據(jù)拆成多張表來(lái)存放。 這里寫圖片描述 這里寫圖片描述 通常情況下,我們使用取模的方式來(lái)進(jìn)行表的拆分;比如一張有400W的用戶表users,為提高其查詢效率我們把其分成4張表users1,users2,users3,users4 通過(guò)用ID取模的方法把數(shù)據(jù)分散到四張表內(nèi)Id%4+1 = [1,2,3,4] 然后查詢,更新,刪除也是通過(guò)取模的方法來(lái)查詢。例:QQ的登錄表。假設(shè)QQ的用戶有100億,如果只有一張表,每個(gè)用戶登錄的時(shí)候數(shù)據(jù)庫(kù)都要從這100億中查找,會(huì)很慢很慢。如果將這一張表分成100份,每張表有1億條,就小了很多,比如qq0,qq1,qq1…qq99表。用戶登錄的時(shí)候,可以將用戶的id%100,那么會(huì)得到0-99的數(shù),查詢表的時(shí)候,將表名qq跟取模的數(shù)連接起來(lái),就構(gòu)建了表名。比如123456789用戶,取模的89,那么就到qq89表查詢,查詢的時(shí)間將會(huì)大大縮短。另外部分業(yè)務(wù)邏輯也可以通過(guò)地區(qū),年份等字段來(lái)進(jìn)行歸檔拆分;進(jìn)行拆分后的表,只能滿足部分查詢的高效查詢需求,這時(shí)我們就要在產(chǎn)品策劃上,從界面上約束用戶查詢行為。比如我們是按年來(lái)進(jìn)行歸檔拆分的,這個(gè)時(shí)候在頁(yè)面設(shè)計(jì)上就約束用戶必須要先選擇年,然后才能進(jìn)行查詢;在做分析或者統(tǒng)計(jì)時(shí),由于是自己人的需求,多點(diǎn)等待其實(shí)是沒(méi)關(guān)系的,并且并發(fā)很低,這個(gè)時(shí)候可以用union把所有表都組合成一張視圖來(lái)進(jìn)行查詢,然后再進(jìn)行查詢。水平拆分的優(yōu)點(diǎn): ◆表關(guān)聯(lián)基本能夠在數(shù)據(jù)庫(kù)端全部完成; ◆不會(huì)存在某些超大型數(shù)據(jù)量和高負(fù)載的表遇到瓶頸的問(wèn)題; ◆應(yīng)用程序端整體架構(gòu)改動(dòng)相對(duì)較少; ◆事務(wù)處理相對(duì)簡(jiǎn)單; ◆只要切分規(guī)則能夠定義好,基本上較難遇到擴(kuò)展性限制;水平切分的缺點(diǎn): ◆切分規(guī)則相對(duì)更為復(fù)雜,很難抽象出一個(gè)能夠滿足整個(gè)數(shù)據(jù)庫(kù)的切分規(guī)則; ◆后期數(shù)據(jù)的維護(hù)難度有所增加,人為手工定位數(shù)據(jù)更困難; ◆應(yīng)用系統(tǒng)各模塊耦合度較高,可能會(huì)對(duì)后面數(shù)據(jù)的遷移拆分造成一定的困難。垂直拆分 垂直拆分是指數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表。表的記錄并不多,但是字段卻很長(zhǎng),表占用空間很大,檢索表的時(shí)候需要執(zhí)行大量的IO,嚴(yán)重降低了性能。這時(shí)需要把大的字段拆分到另一個(gè)表,并且該表與原表是一對(duì)一的關(guān)系。 這里寫圖片描述 這里寫圖片描述通常我們按以下原則進(jìn)行垂直拆分: 1,把不常用的字段單獨(dú)放在一張表;, 2,把text,blob等大字段拆分出來(lái)放在附表中; 3,經(jīng)常組合查詢的列放在一張表中;例如學(xué)生答題表tt:有如下字段: Id name 分?jǐn)?shù) 題目 回答 其中題目和回答是比較大的字段,id name 分?jǐn)?shù)比較小。如果我們只想查詢id為8的學(xué)生的分?jǐn)?shù):select 分?jǐn)?shù) from tt where id = 8;雖然知識(shí)查詢分?jǐn)?shù),但是題目和回答這兩個(gè)大字段也是要被掃描的,很消耗性能。但是我們只關(guān)心分?jǐn)?shù),并不想查詢題目和回答。這就可以使用垂直分割。我們可以把題目單獨(dú)放到一張表中,通過(guò)id與tt表建立一對(duì)一的關(guān)系,同樣將回答單獨(dú)放到一張表中。這樣我們插敘tt中的分?jǐn)?shù)的時(shí)候就不會(huì)掃描題目和回答了。垂直切分的優(yōu)點(diǎn) ◆ 數(shù)據(jù)庫(kù)的拆分簡(jiǎn)單明了,拆分規(guī)則明確; ◆ 應(yīng)用程序模塊清晰明確,整合容易; ◆ 數(shù)據(jù)維護(hù)方便易行,容易定位;垂直切分的缺點(diǎn) ◆ 部分表關(guān)聯(lián)無(wú)法在數(shù)據(jù)庫(kù)級(jí)別完成,需要在程序中完成; ◆ 對(duì)于訪問(wèn)極其頻繁且數(shù)據(jù)量超大的表仍然存在性能平靜,不一定能滿足要求; ◆ 事務(wù)處理相對(duì)更為復(fù)雜; ◆ 切分達(dá)到一定程度之后,擴(kuò)展性會(huì)遇到限制; ◆ 過(guò)讀切分可能會(huì)帶來(lái)系統(tǒng)過(guò)渡復(fù)雜而難以維護(hù)。 ----------------------------------------------------------------------- 數(shù)據(jù)庫(kù)垂直拆分 水平拆分當(dāng)我們使用讀寫分離、緩存后,數(shù)據(jù)庫(kù)的壓力還是很大的時(shí)候,這就需要使用到數(shù)據(jù)庫(kù)拆分了。數(shù)據(jù)庫(kù)拆分簡(jiǎn)單來(lái)說(shuō),就是指通過(guò)某種特定的條件,按照某個(gè)維度,將我們存放在同一個(gè)數(shù)據(jù)庫(kù)中的數(shù)據(jù)分散存放到多個(gè)數(shù)據(jù)庫(kù)(主機(jī))上面以達(dá)到分散單庫(kù)(主機(jī))負(fù)載的效果。 切分模式: 垂直(縱向)拆分、水平拆分。垂直拆分專庫(kù)專用一個(gè)數(shù)據(jù)庫(kù)由很多表的構(gòu)成,每個(gè)表對(duì)應(yīng)著不同的業(yè)務(wù),垂直切分是指按照業(yè)務(wù)將表進(jìn)行分類,分布到不同的數(shù)據(jù)庫(kù)上面,這樣也就將數(shù)據(jù)或者說(shuō)壓力分擔(dān)到不同的庫(kù)上面,如下圖:優(yōu)點(diǎn):1. 拆分后業(yè)務(wù)清晰,拆分規(guī)則明確。2. 系統(tǒng)之間整合或擴(kuò)展容易。3. 數(shù)據(jù)維護(hù)簡(jiǎn)單。缺點(diǎn):1. 部分業(yè)務(wù)表無(wú)法join,只能通過(guò)接口方式解決,提高了系統(tǒng)復(fù)雜度。2. 受每種業(yè)務(wù)不同的限制存在單庫(kù)性能瓶頸,不易數(shù)據(jù)擴(kuò)展跟性能提高。3. 事務(wù)處理復(fù)雜。水平拆分垂直拆分后遇到單機(jī)瓶頸,可以使用水平拆分。相對(duì)于垂直拆分的區(qū)別是:垂直拆分是把不同的表拆到不同的數(shù)據(jù)庫(kù)中,而水平拆分是把同一個(gè)表拆到不同的數(shù)據(jù)庫(kù)中。相對(duì)于垂直拆分,水平拆分不是將表的數(shù)據(jù)做分類,而是按照某個(gè)字段的某種規(guī)則來(lái)分散到多個(gè)庫(kù)之中,每個(gè)表中包含一部分?jǐn)?shù)據(jù)。簡(jiǎn)單來(lái)說(shuō),我們可以將數(shù)據(jù)的水平切分理解為是按照數(shù)據(jù)行的切分,就是將表中 的某些行切分到一個(gè)數(shù)據(jù)庫(kù),而另外的某些行又切分到其他的數(shù)據(jù)庫(kù)中,主要有分表,分庫(kù)兩種模式,如圖:優(yōu)點(diǎn):1. 不存在單庫(kù)大數(shù)據(jù),高并發(fā)的性能瓶頸。2. 對(duì)應(yīng)用透明,應(yīng)用端改造較少。 3. 按照合理拆分規(guī)則拆分,join操作基本避免跨庫(kù)。4. 提高了系統(tǒng)的穩(wěn)定性跟負(fù)載能力。缺點(diǎn):1. 拆分規(guī)則難以抽象。2. 分片事務(wù)一致性難以解決。3. 數(shù)據(jù)多次擴(kuò)展難度跟維護(hù)量極大。4. 跨庫(kù)join性能較差。拆分的處理難點(diǎn)兩張方式共同缺點(diǎn)1. 引入分布式事務(wù)的問(wèn)題。2. 跨節(jié)點(diǎn)Join 的問(wèn)題。3. 跨節(jié)點(diǎn)合并排序分頁(yè)問(wèn)題。針對(duì)數(shù)據(jù)源管理,目前主要有兩種思路:A. 客戶端模式,在每個(gè)應(yīng)用程序模塊中配置管理自己需要的一個(gè)(或者多個(gè))數(shù)據(jù)源,直接訪問(wèn)各個(gè) 數(shù)據(jù)庫(kù),在模塊內(nèi)完成數(shù)據(jù)的整合。 優(yōu)點(diǎn):相對(duì)簡(jiǎn)單,無(wú)性能損耗。 缺點(diǎn):不夠通用,數(shù)據(jù)庫(kù)連接的處理復(fù)雜,對(duì)業(yè)務(wù)不夠透明,處理復(fù)雜。B. 通過(guò)中間代理層來(lái)統(tǒng)一管理所有的數(shù)據(jù)源,后端數(shù)據(jù)庫(kù)集群對(duì)前端應(yīng)用程序透明; 優(yōu)點(diǎn):通用,對(duì)應(yīng)用透明,改造少。 缺點(diǎn):實(shí)現(xiàn)難度大,有二次轉(zhuǎn)發(fā)性能損失。拆分原則1. 盡量不拆分,架構(gòu)是進(jìn)化而來(lái),不是一蹴而就。(SOA)2. 最大可能的找到最合適的切分維度。3. 由于數(shù)據(jù)庫(kù)中間件對(duì)數(shù)據(jù)Join 實(shí)現(xiàn)的優(yōu)劣難以把握,而且實(shí)現(xiàn)高性能難度極大,業(yè)務(wù)讀取 盡量少使用多表Join -盡量通過(guò)數(shù)據(jù)冗余,分組避免數(shù)據(jù)垮庫(kù)多表join。4. 盡量避免分布式事務(wù)。5. 單表拆分到數(shù)據(jù)1000萬(wàn)以內(nèi)。切分方案范圍、枚舉、時(shí)間、取模、哈希、指定等案例分析場(chǎng)景一 建立一個(gè)歷史his系統(tǒng),將公司的一些歷史個(gè)人游戲數(shù)據(jù)保存到這個(gè)his系統(tǒng)中,主要是寫入,還有部分查詢,讀寫比約為1:4;由于是所有數(shù)據(jù)的歷史存取,所以并發(fā)要求比較高; 分析: 歷史數(shù)據(jù) 寫多都少 越近日期查詢?cè)筋l繁? 什么業(yè)務(wù)數(shù)據(jù)?用戶游戲數(shù)據(jù) 有沒(méi)有大規(guī)模分析查詢? 數(shù)據(jù)量多大? 保留多久? 機(jī)器資源有多少?方案1:按照日期每月一個(gè)分片 帶來(lái)的問(wèn)題:1.數(shù)據(jù)熱點(diǎn)問(wèn)題(壓力不均勻)方案2:按照用戶取模, --by Jerome 就這個(gè)比較合適了 帶來(lái)的問(wèn)題:后續(xù)擴(kuò)容困難方案3:按用戶ID范圍分片(1-1000萬(wàn)=分片1,xxx) 帶來(lái)的問(wèn)題:用戶活躍度無(wú)法掌握,可能存在熱點(diǎn)問(wèn)題場(chǎng)景二 建立一個(gè)商城訂單系統(tǒng),保存用戶訂單信息。分析: 電商系統(tǒng) 一號(hào)店或京東類?淘寶或天貓? 實(shí)時(shí)性要求高 存在瞬時(shí)壓力 基本不存在大規(guī)模分析 數(shù)據(jù)規(guī)模? 機(jī)器資源有多少? 維度?商品?用戶?商戶?方案1:按照用戶取模, 帶來(lái)的問(wèn)題:后續(xù)擴(kuò)容困難方案2:按用戶ID范圍分片(1-1000萬(wàn)=分片1,xxx) 帶來(lái)的問(wèn)題:用戶活躍度無(wú)法掌握,可能存在熱點(diǎn)問(wèn)題方案3:按省份地區(qū)或者商戶取模 數(shù)據(jù)分配不一定均勻場(chǎng)景3 上海公積金,養(yǎng)老金,社保系統(tǒng)分析: 社保系統(tǒng) 實(shí)時(shí)性要求不高 不存在瞬時(shí)壓力 大規(guī)模分析? 數(shù)據(jù)規(guī)模大 數(shù)據(jù)重要不可丟失 偏于查詢?方案1:按照用戶取模, 帶來(lái)的問(wèn)題:后續(xù)擴(kuò)容困難方案2:按用戶ID范圍分片(1-1000萬(wàn)=分片1,xxx) 帶來(lái)的問(wèn)題:用戶活躍度無(wú)法掌握,可能存在熱點(diǎn)問(wèn)題方案3:按省份區(qū)縣地區(qū)枚舉 數(shù)據(jù)分配不一定均勻數(shù)據(jù)庫(kù)問(wèn)題解決后,應(yīng)用面對(duì)的新挑戰(zhàn)就是拆分應(yīng)用等參考Mycat在線視頻培訓(xùn)【鏈接:http://pan.baidu.com/s/1nuR26rZ 密碼:1gr9 (2015)】大型網(wǎng)站系統(tǒng)與Java中間件實(shí)踐.pdfMySQL數(shù)據(jù)庫(kù)的演化可以參考:http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=207666963&idx=2&sn=0d0710e071420c6fc6af8d4a3bc3dfe6&scene=1#rdhttp://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651959773&idx=1&sn=7e4ad0dcd050f6662dfaf39d9de36f2c&chksm=bd2d04018a5a8d17b92098b4840aac23982e32d179cdd957e4c55011f6a08f6bd31f9ba5cfee&mpshare=1&scene=23&srcid=1220t4ttl8wZaYHlQRzO0xYB#rd【一分鐘掌握數(shù)據(jù)庫(kù)垂直拆分-沈劍】垂直拆分垂直拆分就是要把表按模塊劃分到不同數(shù)據(jù)庫(kù)表中(當(dāng)然原則還是不破壞第三范式),這種拆分在大型網(wǎng)站的演變過(guò)程中是很常見(jiàn)的。當(dāng)一個(gè)網(wǎng)站還在很小的時(shí)候,只有小量的人來(lái)開(kāi)發(fā)和維護(hù),各模塊和表都在一起,當(dāng)網(wǎng)站不斷豐富和壯大的時(shí)候,也會(huì)變成多個(gè)子系統(tǒng)來(lái)支撐,這時(shí)就有按模塊和功能把表劃分出來(lái)的需求。其實(shí),相對(duì)于垂直切分更進(jìn)一步的是服務(wù)化改造,說(shuō)得簡(jiǎn)單就是要把原來(lái)強(qiáng)耦合的系統(tǒng)拆分成多個(gè)弱耦合的服務(wù),通過(guò)服務(wù)間的調(diào)用來(lái)滿足業(yè)務(wù)需求看,因此表拆出來(lái)后要通過(guò)服務(wù)的形式暴露出去,而不是直接調(diào)用不同模塊的表,淘寶在架構(gòu)不斷演變過(guò)程,最重要的一環(huán)就是服務(wù)化改造,把用戶、交易、店鋪、寶貝這些核心的概念抽取成獨(dú)立的服務(wù),也非常有利于進(jìn)行局部的優(yōu)化和治理,保障核心模塊的穩(wěn)定性垂直拆分:單表大數(shù)據(jù)量依然存在性能瓶頸水平拆分上面談到垂直切分只是把表按模塊劃分到不同數(shù)據(jù)庫(kù),但沒(méi)有解決單表大數(shù)據(jù)量的問(wèn)題,而水平切分就是要把一個(gè)表按照某種規(guī)則把數(shù)據(jù)劃分到不同表或數(shù)據(jù)庫(kù)里。例如像計(jì)費(fèi)系統(tǒng),通過(guò)按時(shí)間來(lái)劃分表就比較合適,因?yàn)橄到y(tǒng)都是處理某一時(shí)間段的數(shù)據(jù)。而像SaaS應(yīng)用,通過(guò)按用戶維度來(lái)劃分?jǐn)?shù)據(jù)比較合適,因?yàn)橛脩襞c用戶之間的隔離的,一般不存在處理多個(gè)用戶數(shù)據(jù)的情況,簡(jiǎn)單的按user_id范圍來(lái)水平切分通俗理解:水平拆分行,行數(shù)據(jù)拆分到不同表中, 垂直拆分列,表數(shù)據(jù)拆分到不同表中垂直與水平聯(lián)合切分由上面可知垂直切分能更清晰化模塊劃分,區(qū)分治理,水平切分能解決大數(shù)據(jù)量性能瓶頸問(wèn)題,因此常常就會(huì)把兩者結(jié)合使用,這在大型網(wǎng)站里是種常見(jiàn)的策略案例:以mysql為例,簡(jiǎn)單購(gòu)物系統(tǒng)暫設(shè)涉及如下表:1.產(chǎn)品表(數(shù)據(jù)量10w,穩(wěn)定)2.訂單表(數(shù)據(jù)量200w,且有增長(zhǎng)趨勢(shì))3.用戶表 (數(shù)據(jù)量100w,且有增長(zhǎng)趨勢(shì))以mysql為例講述下水平拆分和垂直拆分,mysql能容忍的數(shù)量級(jí)在百萬(wàn)靜態(tài)數(shù)據(jù)可以到千萬(wàn)垂直拆分:解決問(wèn)題:表與表之間的io競(jìng)爭(zhēng)不解決問(wèn)題:單表中數(shù)據(jù)量增長(zhǎng)出現(xiàn)的壓力方案:把產(chǎn)品表和用戶表放到一個(gè)server上訂單表單獨(dú)放到一個(gè)server上水平拆分:解決問(wèn)題:單表中數(shù)據(jù)量增長(zhǎng)出現(xiàn)的壓力不解決問(wèn)題:表與表之間的io爭(zhēng)奪方案:用戶表通過(guò)性別拆分為男用戶表和女用戶表訂單表通過(guò)已完成和完成中拆分為已完成訂單和未完成訂單產(chǎn)品表 未完成訂單放一個(gè)server上已完成訂單表盒男用戶表放一個(gè)server上女用戶表放一個(gè)server上(女的愛(ài)購(gòu)物)《大型網(wǎng)站系統(tǒng)與Java中間件實(shí)踐》本書圍繞大型網(wǎng)站和支撐大型網(wǎng)站架構(gòu)的 Java 中間件的實(shí)踐展開(kāi)介紹。從分布式系統(tǒng)的知識(shí)切入,讓讀者對(duì)分布式系統(tǒng)有基本的了解;然后介紹大型網(wǎng)站隨著數(shù)據(jù)量、訪問(wèn)量增長(zhǎng)而發(fā)生的架構(gòu)變遷;接著講述構(gòu)建 Java 中間件的相關(guān)知識(shí);之后的幾章都是根據(jù)筆者的經(jīng)驗(yàn)來(lái)介紹支撐大型網(wǎng)站架構(gòu)的 Java 中間件系統(tǒng)的設(shè)計(jì)和實(shí)踐。本節(jié)為大家介紹專庫(kù)專用,數(shù)據(jù)垂直拆分。AD: 51CTO 網(wǎng)+ 第十二期沙龍:大話數(shù)據(jù)之美_如何用數(shù)據(jù)驅(qū)動(dòng)用戶體驗(yàn)2.2.7 讀寫分離后,數(shù)據(jù)庫(kù)又遇到瓶頸通過(guò)讀寫分離以及在某些場(chǎng)景用分布式存儲(chǔ)系統(tǒng)替換關(guān)系型數(shù)據(jù)庫(kù)的方式,能夠降低主庫(kù)的壓力,解決數(shù)據(jù)存儲(chǔ)方面的問(wèn)題。不過(guò)隨著業(yè)務(wù)的發(fā)展,我們的主庫(kù)也會(huì)遇到瓶頸。我們的網(wǎng)站演進(jìn)到現(xiàn)在,交易、商品、用戶的數(shù)據(jù)還都在一個(gè)數(shù)據(jù)庫(kù)中。盡管采取了增加緩存、讀寫分離的方式,這個(gè)數(shù)據(jù)庫(kù)的壓力還是在繼續(xù)增加,因此我們需要去解決這個(gè)問(wèn)題,我們有數(shù)據(jù)垂直拆分和水平拆分兩種選擇。2.2.7.1 專庫(kù)專用,數(shù)據(jù)垂直拆分垂直拆分的意思是把數(shù)據(jù)庫(kù)中不同的業(yè)務(wù)數(shù)據(jù)拆分到不同的數(shù)據(jù)庫(kù)中。結(jié)合現(xiàn)在的例子,就是把交易、商品、用戶的數(shù)據(jù)分開(kāi),如圖2-20 所示。這樣的變化給我們帶來(lái)的影響是什么呢?應(yīng)用需要配置多個(gè)數(shù)據(jù)源,這就增加了所需的配置,不過(guò)帶來(lái)的是每個(gè)數(shù)據(jù)庫(kù)連接池的隔離。不同業(yè)務(wù)的數(shù)據(jù)從原來(lái)的一個(gè)數(shù)據(jù)庫(kù)中拆分到了多個(gè)數(shù)據(jù)庫(kù)中,那么就需要考慮如何處理原來(lái)單機(jī)中跨業(yè)務(wù)的事務(wù)。一種辦法是使用分布式事務(wù),其性能要明顯低于之前的單機(jī)事務(wù);而另一種辦法就是去掉事務(wù)或者不去追求強(qiáng)事務(wù)支持,則原來(lái)在單庫(kù)中可以使用的表關(guān)聯(lián)的查詢也就需要改變實(shí)現(xiàn)了。對(duì)數(shù)據(jù)進(jìn)行垂直拆分之后,解決了把所有業(yè)務(wù)數(shù)據(jù)放在一個(gè)數(shù)據(jù)庫(kù)中的壓力問(wèn)題。并且也可以根據(jù)不同業(yè)務(wù)的特點(diǎn)進(jìn)行更多優(yōu)化。2.2.7.2 垂直拆分后的單機(jī)遇到瓶頸,數(shù)據(jù)水平拆分與數(shù)據(jù)垂直拆分對(duì)應(yīng)的還有數(shù)據(jù)水平拆分。數(shù)據(jù)水平拆分就是把同一個(gè)表的數(shù)據(jù)拆到兩個(gè)數(shù)據(jù)庫(kù)中。產(chǎn)生數(shù)據(jù)水平拆分的原因是某個(gè)業(yè)務(wù)的數(shù)據(jù)表的數(shù)據(jù)量或者更新量達(dá)到了單個(gè)數(shù)據(jù)庫(kù)的瓶頸,這時(shí)就可以把這個(gè)表拆到兩個(gè)或者多個(gè)數(shù)據(jù)庫(kù)中。數(shù)據(jù)水平拆分與讀寫分離的區(qū)別是,讀寫分離解決的是讀壓力大的問(wèn)題,對(duì)于數(shù)據(jù)量大或者更新量的情況并不起作用。數(shù)據(jù)水平拆分與數(shù)據(jù)垂直拆分的區(qū)別是,垂直拆分是把不同的表拆到不同的數(shù)據(jù)庫(kù)中,而水平拆分是把同一個(gè)表拆到不同的數(shù)據(jù)庫(kù)中。例如,經(jīng)過(guò)垂直拆分后,用戶表與交易表、商品表不在一個(gè)數(shù)據(jù)庫(kù)中了,如果數(shù)據(jù)量或者更新量太大,我們可以進(jìn)一步把用戶表拆分到兩個(gè)數(shù)據(jù)庫(kù)中,它們擁有結(jié)構(gòu)一模一樣的用戶表,而且每個(gè)庫(kù)中的用戶表都只涵蓋了一部分的用戶,兩個(gè)數(shù)據(jù)庫(kù)的用戶合在一起就相當(dāng)于沒(méi)有拆分之前的用戶表。我們先來(lái)簡(jiǎn)單看一下引入數(shù)據(jù)水平拆分后的結(jié)構(gòu),如圖2-21 所示。我們來(lái)分析一下水平拆分后給業(yè)務(wù)應(yīng)用帶來(lái)的影響。首先,訪問(wèn)用戶信息的應(yīng)用系統(tǒng)需要解決SQL 路由的問(wèn)題,因?yàn)楝F(xiàn)在用戶信息分在了兩個(gè)數(shù)據(jù)庫(kù)中,需要在進(jìn)行數(shù)據(jù)庫(kù)操作時(shí)了解需要操作的數(shù)據(jù)在哪里。此外,主鍵的處理也會(huì)變得不同。原來(lái)依賴單個(gè)數(shù)據(jù)庫(kù)的一些機(jī)制需要變化,例如原來(lái)使用Oracle 的Sequence 或者M(jìn)ySQL 表上的自增字段的,現(xiàn)在不能簡(jiǎn)單地繼續(xù)使用了。并且在不同的數(shù)據(jù)庫(kù)中也不能直接使用一些數(shù)據(jù)庫(kù)的限制來(lái)保證主鍵不重復(fù)了。最后,由于同一個(gè)業(yè)務(wù)的數(shù)據(jù)被拆分到了不同的數(shù)據(jù)庫(kù)中,因此一些查詢需要從兩個(gè)數(shù)據(jù)庫(kù)中取數(shù)據(jù),如果數(shù)據(jù)量太大而需要分頁(yè),就會(huì)比較難處理了。不過(guò),一旦我們能夠完成數(shù)據(jù)的水平拆分,我們將能夠很好地應(yīng)對(duì)數(shù)據(jù)量及寫入量增長(zhǎng)的情況。具體如何完成數(shù)據(jù)水平拆分,在后面分布式數(shù)據(jù)訪問(wèn)層的章節(jié)中我們將進(jìn)行更加詳細(xì)的介紹。2.2.8 數(shù)據(jù)庫(kù)問(wèn)題解決后,應(yīng)用面對(duì)的新挑戰(zhàn)2.2.8.1 拆分應(yīng)用前面所講的讀寫分離、分布式存儲(chǔ)、數(shù)據(jù)垂直拆分和數(shù)據(jù)水平拆分都是在解決數(shù)據(jù)方面的問(wèn)題。下面我們來(lái)看看應(yīng)用方面的變化。之前解決了應(yīng)用服務(wù)器從單機(jī)到多機(jī)的擴(kuò)展,應(yīng)用就可以在一定范圍內(nèi)水平擴(kuò)展了。隨著業(yè)務(wù)的發(fā)展,應(yīng)用的功能會(huì)越來(lái)越多,應(yīng)用也會(huì)越來(lái)越大。我們需要考慮如何不讓應(yīng)用持續(xù)變大,這就需要把應(yīng)用拆開(kāi),從一個(gè)應(yīng)用變?yōu)閮蓚€(gè)甚至多個(gè)應(yīng)用。我們來(lái)看兩種方式。第一種方式,根據(jù)業(yè)務(wù)的特性把應(yīng)用拆開(kāi)。在我們的例子中,主要的業(yè)務(wù)功能分為三大部分:交易、商品和用戶。我們可以把原來(lái)的一個(gè)應(yīng)用拆成分別以交易和商品為主的兩個(gè)應(yīng)用,對(duì)于交易和商品都會(huì)有涉及用戶的地方,我們讓這兩個(gè)系統(tǒng)自己完成涉及用戶的工作,而類似用戶注冊(cè)、登錄等基礎(chǔ)的用戶工作,可以暫時(shí)交給兩系統(tǒng)之一來(lái)完成(注意,我們?cè)谶@里主要是通過(guò)例子說(shuō)明拆分的做法),如圖2-22 所示,這樣的拆分可以使大的應(yīng)用變小。我們還可以按照用戶注冊(cè)、用戶登錄、用戶信息維護(hù)等再拆分,使之變成三個(gè)系統(tǒng)。不過(guò),這樣拆分后在不同系統(tǒng)中會(huì)有一些相似的代碼,例如用戶相關(guān)的代碼。如何能夠保證這部分代碼的一致以及如何對(duì)其復(fù)用是需要解決的問(wèn)題。此外,按這樣的方式拆分出來(lái)的新系統(tǒng)之間一般沒(méi)有直接的相互調(diào)用。而且,新拆出來(lái)的應(yīng)用可能會(huì)連接同樣的數(shù)據(jù)庫(kù)。來(lái)看一個(gè)具體的例子,如圖2-23 所示。我們根據(jù)業(yè)務(wù)的不同功能拆分了幾個(gè)業(yè)務(wù)應(yīng)用,而且這些業(yè)務(wù)應(yīng)用之間不存在直接的調(diào)用,它們都依賴底層的數(shù)據(jù)庫(kù)、緩存、文件系統(tǒng)、搜索等。這樣的應(yīng)用拆分確實(shí)能夠解決當(dāng)下的一些問(wèn)題,不過(guò)也有一些缺點(diǎn)。 2.2.8.2 走服務(wù)化的路我們?cè)賮?lái)看一下服務(wù)化的做法。圖2-24 是一個(gè)示意圖。從中可以看到我們把應(yīng)用分為了三層,處于最上端的是Web 系統(tǒng),用于完成不同的業(yè)務(wù)功能;處于中間的是一些服務(wù)中心,不同的服務(wù)中心提供不同的業(yè)務(wù)服務(wù);處于下層的則是業(yè)務(wù)的數(shù)據(jù)庫(kù)。當(dāng)然,我們?cè)谶@個(gè)圖中省去了緩存等基礎(chǔ)的系統(tǒng),因此可以說(shuō)是服務(wù)化系統(tǒng)結(jié)構(gòu)的一個(gè)簡(jiǎn)圖。圖2-24 與之前的圖相比有幾個(gè)很重要的變化。首先,業(yè)務(wù)功能之間的訪問(wèn)不僅是單機(jī)內(nèi)部的方法調(diào)用了,還引入了遠(yuǎn)程的服務(wù)調(diào)用。其次,共享的代碼不再是散落在不同的應(yīng)用中了,這些實(shí)現(xiàn)被放在了各個(gè)服務(wù)中心。第三,數(shù)據(jù)庫(kù)的連接也發(fā)生了一些變化,我們把與數(shù)據(jù)庫(kù)的交互工作放到了服務(wù)中心,讓前端的Web 應(yīng)用更加注重與瀏覽器交互的工作,而不必過(guò)多關(guān)注業(yè)務(wù)邏輯的事情。連接數(shù)據(jù)庫(kù)的任務(wù)交給相應(yīng)的業(yè)務(wù)服務(wù)中心了,這樣可以降低數(shù)據(jù)庫(kù)的連接數(shù)。而服務(wù)中心不僅把一些可以共用的之前散落在各個(gè)業(yè)務(wù)的代碼集中了起來(lái),并且能夠使這些代碼得到更好的維護(hù)。第四,通過(guò)服務(wù)化,無(wú)論是前端Web 應(yīng)用還是服務(wù)中心,都可以是由固定小團(tuán)隊(duì)來(lái)維護(hù)的系統(tǒng),這樣能夠更好地保持穩(wěn)定性,并能更好地控制系統(tǒng)本身的發(fā)展,況且穩(wěn)定的服務(wù)中心日常發(fā)布的次數(shù)也遠(yuǎn)小于前端Web 應(yīng)用,因此這個(gè)方式也減小了不穩(wěn)定的風(fēng)險(xiǎn)。要做到服務(wù)化還需要一些基礎(chǔ)組件的支撐,在后面服務(wù)框架的章節(jié)我們會(huì)具體介紹。通過(guò)某種特定的條件,將存放在同一個(gè)數(shù)據(jù)庫(kù)中的數(shù)據(jù)分散存放到多個(gè)數(shù)據(jù)庫(kù)上,實(shí)現(xiàn)分布存儲(chǔ),通過(guò)路由規(guī)則路由訪問(wèn)特定的數(shù)據(jù)庫(kù),這樣一來(lái)每次訪問(wèn)面對(duì)的就不是單臺(tái)服務(wù)器了,而是N臺(tái)服務(wù)器,這樣就可以降低單臺(tái)機(jī)器的負(fù)載壓力。提示:sqlserver 2005版本之后,可以友好的支持“表分區(qū)”。垂直(縱向)拆分:是指按功能模塊拆分,比如分為訂單庫(kù)、商品庫(kù)、用戶庫(kù)...這種方式多個(gè)數(shù)據(jù)庫(kù)之間的表結(jié)構(gòu)不同。水平(橫向)拆分:將同一個(gè)表的數(shù)據(jù)進(jìn)行分塊保存到不同的數(shù)據(jù)庫(kù)中,這些數(shù)據(jù)庫(kù)中的表結(jié)構(gòu)完全相同。SQL Server:數(shù)據(jù)庫(kù)/數(shù)據(jù)表 拆分 ▲(縱向拆分)SQL Server:數(shù)據(jù)庫(kù)/數(shù)據(jù)表 拆分 ▲(橫向拆分)1,實(shí)現(xiàn)原理:使用垂直拆分,主要要看應(yīng)用類型是否合適這種拆分方式,如系統(tǒng)可以分為,訂單系統(tǒng),商品管理系統(tǒng),用戶管理系統(tǒng)業(yè)務(wù)系統(tǒng)比較明的,垂直拆分能很好的起到分散數(shù)據(jù)庫(kù)壓力的作用。業(yè)務(wù)模塊不明晰,耦合(表關(guān)聯(lián))度比較高的系統(tǒng)不適合使用這種拆分方式。但是垂直拆分方式并不能徹底解決所有壓力問(wèn)題,例如 有一個(gè)5000w的訂單表,操作起來(lái)訂單庫(kù)的壓力仍然很大,如我們需要在這個(gè)表中增加(insert)一條新的數(shù)據(jù),insert完畢后,數(shù)據(jù)庫(kù)會(huì)針對(duì)這張表重新建立索引,5000w行數(shù)據(jù)建立索引的系統(tǒng)開(kāi)銷還是不容忽視的,反過(guò)來(lái),假如我們將這個(gè)表分成100個(gè)table呢,從table_001一直到table_100,5000w行數(shù)據(jù)平均下來(lái),每個(gè)子表里邊就只有50萬(wàn)行數(shù)據(jù),這時(shí)候我們向一張只有50w行數(shù)據(jù)的table中insert數(shù)據(jù)后建立索引的時(shí)間就會(huì)呈數(shù)量級(jí)的下降,極大了提高了DB的運(yùn)行時(shí)效率,提高了DB的并發(fā)量,這種拆分就是橫向拆分2,實(shí)現(xiàn)方法:垂直拆分,拆分方式實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單,根據(jù)表名訪問(wèn)不同的數(shù)據(jù)庫(kù)就可以了。橫向拆分的規(guī)則很多,這里總結(jié)前人的幾點(diǎn),(1)順序拆分:如可以按訂單的日前按年份才分,2003年的放在db1中,2004年的db2,以此類推。當(dāng)然也可以按主鍵標(biāo)準(zhǔn)拆分。優(yōu)點(diǎn):可部分遷移缺點(diǎn):數(shù)據(jù)分布不均,可能2003年的訂單有100W,2008年的有500W。(2)hash取模分: 對(duì)user_id進(jìn)行hash(或者如果user_id是數(shù)值型的話直接使用user_id的值也可),然后用一個(gè)特定的數(shù)字,比如應(yīng)用中需要將一個(gè)數(shù)據(jù)庫(kù)切分成4個(gè)數(shù)據(jù)庫(kù)的話,我們就用4這個(gè)數(shù)字對(duì)user_id的hash值進(jìn)行取模運(yùn)算,也就是user_id%4,這樣的話每次運(yùn)算就有四種可能:結(jié)果為1的時(shí)候?qū)?yīng)DB1;結(jié)果為2的時(shí)候?qū)?yīng)DB2;結(jié)果為3的時(shí)候?qū)?yīng)DB3;結(jié)果為0的時(shí)候?qū)?yīng)DB4,這樣一來(lái)就非常均勻的將數(shù)據(jù)分配到4個(gè)DB中。優(yōu)點(diǎn):數(shù)據(jù)分布均勻缺點(diǎn):數(shù)據(jù)遷移的時(shí)候麻煩;不能按照機(jī)器性能分?jǐn)倲?shù)據(jù) 。(3)在認(rèn)證庫(kù)中保存數(shù)據(jù)庫(kù)配置就是建立一個(gè)DB,這個(gè)DB單獨(dú)保存user_id到DB的映射關(guān)系,每次訪問(wèn)數(shù)據(jù)庫(kù)的時(shí)候都要先查詢一次這個(gè)數(shù)據(jù)庫(kù),以得到具體的DB信息,然后才能進(jìn)行我們需要的查詢操作。優(yōu)點(diǎn):靈活性強(qiáng),一對(duì)一關(guān)系缺點(diǎn):每次查詢之前都要多一次查詢,會(huì)造成一定的性能損失。------------------------------------------------------------------------------ mysql數(shù)據(jù)庫(kù)的水平拆分與垂直拆分 近端時(shí)間在面試,發(fā)現(xiàn)很多面試官或者面試都把數(shù)據(jù)的水平拆分合垂直拆分給搞混了,今天特意寫了一篇博客來(lái)說(shuō)說(shuō)水平拆分和垂直拆分希望對(duì)程序猿們有所幫助。數(shù)據(jù)庫(kù)水平與垂直拆分:垂直(縱向)拆分:是指按功能模塊拆分,比如分為訂單庫(kù)、商品庫(kù)、用戶庫(kù)...這種方式多個(gè)數(shù)據(jù)庫(kù)之間的表結(jié)構(gòu)不同。水平(橫向)拆分:將同一個(gè)表的數(shù)據(jù)進(jìn)行分塊保存到不同的數(shù)據(jù)庫(kù)中,這些數(shù)據(jù)庫(kù)中的表結(jié)構(gòu)完全相同。數(shù)據(jù)表的水平與垂直拆分:垂直拆分:按字段功能主次拆分,比如最常見(jiàn)的商品表、商品圖片表、商品詳細(xì)信息...表與表之間的結(jié)構(gòu)不同水平拆分:同數(shù)據(jù)庫(kù)的水平拆分原理一樣主要是將數(shù)據(jù)進(jìn)行拆分保存到不同的表當(dāng)中,這些表的結(jié)構(gòu)完全相同。、使用用垂直拆分要主要看系統(tǒng)是否適合這種拆分方式,如系統(tǒng)可分為用戶系統(tǒng),商品系統(tǒng)、訂單系統(tǒng)等這些業(yè)務(wù)比較明確的比較適合使用垂直拆分,垂直拆分能很好分散數(shù)據(jù)庫(kù)壓力。業(yè)務(wù)模塊不清晰,模塊耦合度較高的系統(tǒng)并不適合垂直拆分。垂直拆分并不能徹底解決所有的壓力問(wèn)題,例如有一張8000w的訂單表而且訂單隨著時(shí)間還在一直增加,操作起這張訂單表壓力依然很大,如我們需要在這個(gè)表中增加(insert)一條新的數(shù)據(jù),insert完畢后,數(shù)據(jù)庫(kù)會(huì)針對(duì)這張表重新建立索引,8000w行數(shù)據(jù)建立索引的系統(tǒng)開(kāi)銷還是不容忽視的,這類情況就可以使用到水平拆分了,可以將表分成100個(gè)table,table_001一直到table_100,8000w數(shù)據(jù)平均分下來(lái)就是80萬(wàn)的數(shù)據(jù)(經(jīng)過(guò)實(shí)際測(cè)試mysql數(shù)據(jù)量達(dá)到400w的時(shí)候性能明顯降低,故而應(yīng)將單個(gè)mysql的數(shù)據(jù)量控制在300W以內(nèi)),這時(shí)候我們向一張只有80w行數(shù)據(jù)的table中insert數(shù)據(jù)后建立索引的時(shí)間就會(huì)呈數(shù)量級(jí)的下降,極大了提高了DB的運(yùn)行時(shí)效率,提高了DB的并發(fā)量,這種拆分就是水平(橫向)拆分?jǐn)?shù)據(jù)庫(kù)拆的實(shí)現(xiàn)方式:垂直拆分,拆分方式實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單,根據(jù)表名訪問(wèn)不同的數(shù)據(jù)庫(kù)就可以了這里不多講。橫向拆分的規(guī)則很多,這里總結(jié)了以下幾點(diǎn):1、順序拆分:例如訂單表可以按訂單的日期按年份才分,2016年的放在db1中,2017年的db2,以此類推。當(dāng)然也可以按主鍵標(biāo)準(zhǔn)拆分。優(yōu)點(diǎn):可部分遷移缺點(diǎn):數(shù)據(jù)分布不均,可能2016年的訂單有200W,2017年的有800W。2、hash取模分: 例如訂單表對(duì)user_id進(jìn)行hash(或者如果user_id是數(shù)值型的話直接使用user_id的值也可),然后用一個(gè)特定的數(shù)字,比如應(yīng)用中需要將一個(gè)數(shù)據(jù)庫(kù)切分成4個(gè)數(shù)據(jù)庫(kù)的話,我們就用4這個(gè)數(shù)字對(duì)user_id的hash值進(jìn)行取模運(yùn)算,也就是user_id%4,這樣的話每次運(yùn)算就有四種可能:結(jié)果為1的時(shí)候?qū)?yīng)DB1;結(jié)果為2的時(shí)候?qū)?yīng)DB2;結(jié)果為3的時(shí)候?qū)?yīng)DB3;結(jié)果為0的時(shí)候?qū)?yīng)DB4,這樣一來(lái)就非常均勻的將數(shù)據(jù)分配到4個(gè)DB中。優(yōu)點(diǎn):數(shù)據(jù)分布均勻缺點(diǎn):數(shù)據(jù)遷移的時(shí)候麻煩;不能按照機(jī)器性能分?jǐn)倲?shù)據(jù) 。3、在認(rèn)證庫(kù)中保存數(shù)據(jù)庫(kù)配置,就是建立一個(gè)DB,這個(gè)DB單獨(dú)保存user_id到DB的映射關(guān)系,每次訪問(wèn)數(shù)據(jù)庫(kù)的時(shí)候都要先查詢一次這個(gè)數(shù)據(jù)庫(kù),以得到具體的DB信息,然后才能進(jìn)行我們需要的查詢操作。優(yōu)點(diǎn):靈活性強(qiáng),一對(duì)一關(guān)系缺點(diǎn):每次查詢之前都要多一次查詢,會(huì)造成一定的性能損失。ps:暫時(shí)只想到這些希望對(duì)大家有幫助,如果有更好的方法歡迎留言區(qū)評(píng)論交流 ----------------------------------------------------------------------------

oracle表分區(qū)

oracle表分區(qū)詳解(按天、按月、按年等)分區(qū)表的概念:當(dāng)表中的數(shù)據(jù)量不斷增大,查詢數(shù)據(jù)的速度就會(huì)變慢,應(yīng)用程序的性能就會(huì)下降,這時(shí)就應(yīng)該考慮對(duì)表進(jìn)行分區(qū)。表進(jìn)行分區(qū)后,邏輯上表仍然是一張完整的表,只是將表中的數(shù)據(jù)在物理上存放到多個(gè)表空間(物理文件上),這樣查詢數(shù)據(jù)時(shí),不至于每次都掃描整張表。分區(qū)表的優(yōu)點(diǎn):1) 改善查詢性能:對(duì)分區(qū)對(duì)象的查詢可以僅搜索自己關(guān)心的分區(qū),提高檢索速度。2) 增強(qiáng)可用性:如果表的某個(gè)分區(qū)出現(xiàn)故障,表在其他分區(qū)的數(shù)據(jù)仍然可用;3) 維護(hù)方便:如果表的某個(gè)分區(qū)出現(xiàn)故障,需要修復(fù)數(shù)據(jù),只修復(fù)該分區(qū)即可;4) 均衡I/O:可以把不同的分區(qū)映射到磁盤以平衡I/O,改善整個(gè)系統(tǒng)性能。分區(qū)表的種類:1.范圍分區(qū) 概念: 范圍分區(qū)將數(shù)據(jù)基于范圍映射到每一個(gè)分區(qū),這個(gè)范圍是你在創(chuàng)建分區(qū)時(shí)指定的分區(qū)鍵決定的。這種分區(qū)方式是最為常用的,并且分區(qū)鍵經(jīng)常采用日期。舉個(gè)例子:你可能會(huì)將銷售數(shù)據(jù)按照月份進(jìn)行分區(qū)。-- 按行分區(qū) SQL> CREATE TABLE part_andy12 (3 andy_ID NUMBER NOT NULL PRIMARY KEY,4 FIRST_NAME VARCHAR2(30) NOT NULL,5 LAST_NAME VARCHAR2(30) NOT NULL,6 PHONE VARCHAR2(15) NOT NULL,7 EMAIL VARCHAR2(80),8 STATUS CHAR(1)9 )10 PARTITION BY RANGE (andy_ID)11 (12 PARTITION PART1 VALUES LESS THAN (10000) ,13 PARTITION PART2 VALUES LESS THAN (20000)14 );Table created.-- 按時(shí)間分區(qū)SQL> CREATE TABLE part_andy22 (3 ORDER_ID NUMBER(7) NOT NULL,4 ORDER_DATE DATE,5 OTAL_AMOUNT NUMBER,6 CUSTOTMER_ID NUMBER(7),7 PAID CHAR(1)8 )9 PARTITION BY RANGE (ORDER_DATE)10 (11 PARTITION p1 VALUES LESS THAN (TO_DATE('2014-10-1', 'yyyy-mm-dd')) ,12 PARTITION p2 VALUES LESS THAN (TO_DATE('2015-10-1', 'yyyy-mm-dd')) ,13 PARTITION p3 VALUES LESS THAN (TO_DATE('2016-10-1', 'yyyy-mm-dd')) ,14 partition p4 values less than (maxvalue)15 );Table created.2. Hash分區(qū)概念: 對(duì)于那些無(wú)法有效劃分范圍的表,可以使用hash分區(qū),這樣對(duì)于提高性能還是會(huì)有一定的幫助。hash分區(qū)會(huì)將表中的數(shù)據(jù)平均分配到你指定的幾個(gè)分區(qū)中,列所在分區(qū)是依據(jù)分區(qū)列的hash值自動(dòng)分配,因此你并不能控制也不知道哪條記錄會(huì)被放到哪個(gè)分區(qū)中,hash分區(qū)也可以支持多個(gè)依賴列。注意: hash分區(qū)最主要的機(jī)制是根據(jù)hash算法來(lái)計(jì)算具體某條紀(jì)錄應(yīng)該插入到哪個(gè)分區(qū)中,hash算法中最重要的是hash函數(shù),Oracle中如果你要使用hash分區(qū),只需指定分區(qū)的數(shù)量即可。建議分區(qū)的數(shù)量采用2的n次方,這樣可以使得各個(gè)分區(qū)間數(shù)據(jù)分布更加均勻。--按hash分區(qū) SQL> create table part_andy32 (3 transaction_id number primary key,4 item_id number(8) not null5 )6 partition by hash(transaction_id)7 (8 partition part_01 ,9 partition part_02 ,10 partition part_0311 );Table created.3. List分區(qū)概念: List分區(qū)也需要指定列的值,其分區(qū)值必須明確指定,該分區(qū)列只能有一個(gè),不能像range或者h(yuǎn)ash分區(qū)那樣同時(shí)指定多個(gè)列做為分區(qū)依賴列,但它的單個(gè)分區(qū)對(duì)應(yīng)值可以是多個(gè)。注意: 在分區(qū)時(shí)必須確定分區(qū)列可能存在的值,一旦插入的列值不在分區(qū)范圍內(nèi),則插入/更新就會(huì)失敗,因此通常建議使用list分區(qū)時(shí),要?jiǎng)?chuàng)建一個(gè)default分區(qū)存儲(chǔ)那些不在指定范圍內(nèi)的記錄,類似range分區(qū)中的maxvalue分區(qū)。-- 按list分區(qū) SQL> create table part_andy42 (3 id varchar2(15 byte) not null,4 city varchar2(20)5 )6 partition by list (city)7 (8 partition t_list025 values ('beijing'),9 partition t_list372 values ('shanghai') ,10 partition t_list510 values ('changsha'),11 partition p_other values (default)12 );Table created.4. 組合分區(qū)Oracle10g提供兩種分區(qū)組合 – Range-hash SQL> create table part_andy52 (3 transaction_id number primary key,4 item_id number(8) not null,5 item_description varchar2(300),6 transaction_date date7 )8 partition by range(transaction_date)subpartition by hash(transaction_id)9 (10 partition part_01 values less than(TO_DATE('2014-10-1', 'yyyy-mm-dd')),11 partition part_02 values less than(TO_DATE('2015-10-1', 'yyyy-mm-dd')),12 partition part_03 values less than(maxvalue)13 );Table created.– Range-list SQL> CREATE TABLE SALES2 (3 PRODUCT_ID VARCHAR2(5),4 SALES_DATE DATE,5 SALES_COST NUMBER(10),6 STATUS VARCHAR2(20)7 )8 PARTITION BY RANGE(SALES_DATE) SUBPARTITION BY LIST (STATUS)9 (10 PARTITION P1 VALUES LESS THAN(TO_DATE('2014-10-1', 'yyyy-mm-dd'))11 (SUBPARTITION P1SUB1 VALUES ('ACTIVE') ,SUBPARTITION P1SUB2 VALUES ('INACTIVE')12 ),PARTITION P2 VALUES LESS THAN (TO_DATE('2015-10-1', 'yyyy-mm-dd'))13 (14 SUBPARTITION P2SUB1 VALUES ('ACTIVE') ,15 SUBPARTITION P2SUB2 VALUES ('INACTIVE')16 )17 );Table created.Oracle11g增加了四種組合 – RANGE-RANGE – LIST-RANGE – LIST-HASH – LIST-LIST Oracle 11g 中虛擬列來(lái)實(shí)現(xiàn)。在11g之前 分區(qū)表的partition key必須是物理存在的。11g開(kāi)始提供了虛擬列,并且可以作為partition key 。 --按星期分區(qū) SQL> CREATE TABLE part_andy62 (3 getdate date NOT NULL,4 wd NUMBER GENERATED ALWAYS AS (TO_NUMBER (TO_CHAR (getdate, 'D'))) VIRTUAL5 )6 PARTITION BY LIST (wd)7 (8 PARTITION Mon VALUES (1),9 PARTITION Tue VALUES (2),10 PARTITION Wed VALUES (3),11 PARTITION Thu VALUES (4),12 PARTITION Fri VALUES (5),13 PARTITION Sat VALUES (6),14 PARTITION Sun VALUES (7)15 );Table created.SQL> SQL> insert into part_andy6(getdate) values(sysdate);1 row created.SQL> insert into part_andy6(getdate) values(sysdate-1);1 row created.SQL> insert into part_andy6(getdate) values(sysdate-2);1 row created.SQL> insert into part_andy6(getdate) values(sysdate-3);1 row created.SQL> insert into part_andy6(getdate) values(sysdate-4);1 row created.SQL> insert into part_andy6(getdate) values(sysdate-5);1 row created.SQL> insert into part_andy6(getdate) values(sysdate-6);1 row created.SQL> insert into part_andy6(getdate) values(sysdate-7);1 row created.-- 檢查測(cè)試成功 SQL> select * from part_andy6;GETDATE WD ------------------- ---------- 2014-11-23 16:35:07 1 2014-11-24 16:35:07 2 2014-11-25 16:35:07 3 2014-11-26 16:35:07 4 2014-11-27 16:35:07 5 2014-11-28 16:35:07 6 2014-11-29 16:35:07 7 2014-11-22 16:35:08 78 rows selected.Oracle Database 11g,Interval類型分區(qū)表,可以根據(jù)加載數(shù)據(jù),自動(dòng)創(chuàng)建指定間隔的分區(qū)。創(chuàng)建按月分區(qū)的分區(qū)表:a. 創(chuàng)建分區(qū)表SQL> CREATE TABLE interval_andy7 (a1 NUMBER, a2 DATE)2 PARTITION BY RANGE (a2)3 INTERVAL ( NUMTOYMINTERVAL (1, 'MONTH') )4 (PARTITION part15 VALUES LESS THAN (TO_DATE('2014-11-1', 'yyyy-mm-dd')),6 PARTITION part27 VALUES LESS THAN (TO_DATE('2014-12-1', 'yyyy-mm-dd'))8 );Table created. 注意:如果在建Interval分區(qū)表是沒(méi)有把所有的分區(qū)寫完成,在插入相關(guān)數(shù)據(jù)后會(huì)自動(dòng)生成分區(qū) b. 查看現(xiàn)在表的分區(qū): SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY7'; TABLE_NAME PARTITION_NAME ------------------------------ ------------------------------ INTERVALPART PART1 INTERVALPART PART2 c. 插入測(cè)試數(shù)據(jù): SQL> begin2 for i in 0 .. 11 loop3 insert into interval_andy7 values(i,add_months(to_date('2014-11-1','yyyy-mm-dd'),i));4 end loop ;5 commit;6 end;7 /PL/SQL procedure successfully completed.PL/SQL 過(guò)程已成功完成。 補(bǔ)充:add_months()函數(shù)獲取前一個(gè)月或者下一個(gè)月的月份, 參數(shù)中 負(fù)數(shù) 代表 往前, 正數(shù) 代表 往后。 --上一個(gè)月 select to_char(add_months(trunc(sysdate),-1),'yyyymm') from dual; --下一個(gè)月 select to_char(add_months(trunc(sysdate),1),'yyyymm') from dual; d. 觀察自動(dòng)創(chuàng)建的分區(qū): SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY7';TABLE_NAME PARTITION_NAME ------------------------------ ------------------------------ INTERVAL_ANDY7 PART1 INTERVAL_ANDY7 PART2 INTERVAL_ANDY7 SYS_P24 INTERVAL_ANDY7 SYS_P25 INTERVAL_ANDY7 SYS_P26 INTERVAL_ANDY7 SYS_P27 INTERVAL_ANDY7 SYS_P28 INTERVAL_ANDY7 SYS_P29 INTERVAL_ANDY7 SYS_P30 INTERVAL_ANDY7 SYS_P31 INTERVAL_ANDY7 SYS_P32TABLE_NAME PARTITION_NAME ------------------------------ ------------------------------ INTERVAL_ANDY7 SYS_P33 INTERVAL_ANDY7 SYS_P3413 rows selected.下面創(chuàng)建一個(gè)以天為間隔的分區(qū)表:1. 創(chuàng)建分區(qū)表: SQL> create table interval_andy82 (3 id number,4 dt date5 )6 partition by range (dt)7 INTERVAL (NUMTODSINTERVAL(1,'day'))8 (9 partition p20141101 values less than (to_date('2014-11-1','yyyy-mm-dd'))10 );Table created.2. 查看表分區(qū): SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY8';TABLE_NAME PARTITION_NAME ------------------------------ ------------------------------ INTERVAL_ANDY8 P201411013. 插入測(cè)試數(shù)據(jù): begin for i in 1 .. 12 loop insert into INTERVAL_ANDY8 values(i,trunc(to_date('2014-11-1','yyyy-mm-dd')+i)); end loop; commit; end; / PL/SQL 過(guò)程已成功完成。 4. 觀察自動(dòng)創(chuàng)建的分區(qū): SQL> select table_name,partition_name from user_tab_partitions where table_name='INTERVAL_ANDY8';TABLE_NAME PARTITION_NAME ------------------------------ ------------------------------ INTERVAL_ANDY8 P20141101 INTERVAL_ANDY8 SYS_P35 INTERVAL_ANDY8 SYS_P36 INTERVAL_ANDY8 SYS_P37 INTERVAL_ANDY8 SYS_P38 INTERVAL_ANDY8 SYS_P39 INTERVAL_ANDY8 SYS_P40 INTERVAL_ANDY8 SYS_P41 INTERVAL_ANDY8 SYS_P42 INTERVAL_ANDY8 SYS_P43 INTERVAL_ANDY8 SYS_P44TABLE_NAME PARTITION_NAME ------------------------------ ------------------------------ INTERVAL_ANDY8 SYS_P45 INTERVAL_ANDY8 SYS_P4613 rows selected. -------------------------------------------------------------------------------------- oracle分區(qū)技術(shù)提高查詢效率 概述: 當(dāng)表中的數(shù)據(jù)量不斷增大,查詢數(shù)據(jù)的速度就會(huì)變慢,應(yīng)用程序的性能就會(huì)下降,這時(shí)就應(yīng)該考慮對(duì)表進(jìn)行分區(qū)。表進(jìn)行分區(qū)后,邏輯上表仍然是一張完整的表,只是將表中的數(shù)據(jù)在物理上存放到多個(gè)表空間(物理文件上),這樣查詢數(shù)據(jù)時(shí),不至于每次都掃描整張表。下面介紹如何使用分區(qū)增加查詢效率range分區(qū):就是區(qū)域分區(qū)復(fù)制代碼 CREATE TABLE SALE (PRODUCT_ID VARCHAR2(5),SALE_COUNT NUMBER(10,2) ) PARTITION BY RANGE (SALE_COUNT) (PARTITION P1 VALUES LESS THAN (1000) TABLESPACE CUS_TS01,PARTITION P2 VALUES LESS THAN (2000) TABLESPACE CUS_TS02 ) 復(fù)制代碼 查看分區(qū)語(yǔ)法:select * from user_tab_partitions; --查詢所有分區(qū)情況,可以接條件where table_name='sale'查看分區(qū)表結(jié)構(gòu)select * from sale partition(p1); --查詢某表的某一分區(qū)數(shù)據(jù)分區(qū)后,新增數(shù)據(jù)的SALE_COUNT字段如果小于1000就存儲(chǔ)到P1分區(qū)中,如果1000到2000存儲(chǔ)到P2分區(qū)中。但是這時(shí)如果我們新增的一條數(shù)據(jù)的SALE_COUNT字段值大于2000,將無(wú)法存儲(chǔ)到表中。我們可以擴(kuò)展分區(qū),語(yǔ)法如下:alter table sale add partition p4 values less than(maxvalue); --大于2000的都會(huì)存到此分區(qū)中,當(dāng)然也可以增加更多的分區(qū)同時(shí)可以刪除分區(qū),語(yǔ)法如下:alter table sale drop partition p4; --注意:刪除分區(qū)會(huì)把分區(qū)內(nèi)已有的數(shù)據(jù)同時(shí)刪除但還存在一個(gè)問(wèn)題,如果現(xiàn)在update分區(qū)p1中的SALE_COUNT值為1500,是不會(huì)成功的,需要在update前增加以下語(yǔ)句:alter table sale enable row movement; --使其row能移動(dòng)這樣再update就可以成功了分區(qū)索引 分區(qū)之后雖然可以提高查詢的效率,但也僅僅是提高了數(shù)據(jù)的范圍,所以我們?cè)谟斜匾那闆r下,需要建立分區(qū)索引,從而進(jìn)一步提高效率。分區(qū)索引大體上分為兩大類,一類叫做local,一類叫做global。local:在每個(gè)分區(qū)上建立索引(一般采用這種方式)global:一種在全局上建立索引,這種方式分不分區(qū)都一樣,一般不使用下面進(jìn)行語(yǔ)法演示:注意:分區(qū)上建立的索引一定是分區(qū)字段create index idx_count on sale(sale_count) local;--建立分區(qū)索引,在sale表的每個(gè)分區(qū)都建立了索引select * from user_ind_partitions;--查詢所有分區(qū)索引情況全局索引global寫法就是把上面的local替換成global,但不會(huì)使用有些時(shí)候,如果你分區(qū)分為0~1000,1000~2000,這時(shí)如果說(shuō)0~1500這個(gè)范圍內(nèi)的數(shù)據(jù)會(huì)被頻繁查詢,1500之后查詢很少,那么就可以使用這種自定義的全局索引方式對(duì)0~1500建立索引,之后的設(shè)置maxvalue即可,語(yǔ)法與分區(qū)語(yǔ)法相似global自定義全局索引方式(前綴索引):create index idxname on table(field) globalpartition by range(field) (partition p1 values less than(value), .......partition pN values less than(maxvalue));其他分區(qū)介紹 1.hash分區(qū)hash分區(qū)實(shí)現(xiàn)均勻的負(fù)載值分配,增加hash分區(qū)可以重新分布數(shù)據(jù),簡(jiǎn)單理解就是分區(qū)直接平均分配復(fù)制代碼 CREATE TABLE SALE (PRODUCT_ID VARCHAR2(5),SALE_COUNT NUMBER(10,2) ) PARTITION BY HASH (PRODUCT_ID) (PARTITION P1,PARTITION P2 ) 復(fù)制代碼 2.list分區(qū)該分區(qū)的特點(diǎn)是某列的值只有幾個(gè),基于這樣的特點(diǎn)我們可以采用列表分區(qū)。復(fù)制代碼 CREATE TABLE ListTable (id INT PRIMARY KEY ,name VARCHAR (20),area VARCHAR (10) ) PARTITION BY LIST (area) (PARTITION part1 VALUES ('guangdong','beijing') TABLESPACE Part1_tb,PARTITION part2 VALUES ('shanghai','nanjing') TABLESPACE Part2_tb ); 復(fù)制代碼 3.復(fù)合分區(qū)(用的不多)復(fù)制代碼 create table student(sno number,sname varchar2(10) ) partition by range (sno) subpartition by hash (sname) subpartitions 4 (partition p1 values less than(1000),partition p2 values less than(2000),partition p3 values less than(maxvalue) ); 復(fù)制代碼 復(fù)合分區(qū)首先大體上分為三個(gè)分區(qū)p1,p2,p3,然后每一個(gè)分區(qū)內(nèi)部再進(jìn)行hash分區(qū),分為4份查詢子分區(qū)的語(yǔ)句:select * from user_tab_subpartitions where table_name='student';4.間隔分區(qū)(工作中常用)是一種分區(qū)自動(dòng)化的分區(qū),可以指定時(shí)間間隔進(jìn)行分區(qū),這是oracle11g的新特性,實(shí)際工作中很常用。實(shí)際上是由range分區(qū)引申的,最終實(shí)現(xiàn)了range分區(qū)的自動(dòng)化復(fù)制代碼 create table interval_sale (sid int,sdate timestamp) partition by range(sdate) interval (numtoyminterval(1,'MONTH')) ( partition p1 values less than (TIMESTAMP '2017-11-12 00:00:00.00') ) 復(fù)制代碼 指定時(shí)間之前建立一個(gè)分區(qū),之后每隔一個(gè)月建立一個(gè)分區(qū)問(wèn)題:如果我們drop掉了表,那么這個(gè)表的分區(qū)還存在嗎?答案是存在的,oracle提供了很強(qiáng)大的數(shù)據(jù)恢復(fù)功能,有一個(gè)類似回收站的機(jī)制,刪除表后,分區(qū)以特殊的形式仍然存在user_tab_partitions中,使用purge recyclebin語(yǔ)法后,會(huì)清空回收站,使用flashback table 表名 to before drop語(yǔ)句可以恢復(fù)刪除的表。 ------------------------------------------------------------------------------------- 當(dāng)大家遇到小數(shù)據(jù)的時(shí)候,大家可能想著在where后面多加點(diǎn)約束條件;當(dāng)數(shù)據(jù)在大點(diǎn)的時(shí)候,大家可能就開(kāi)始考慮給這添加索引了;當(dāng)大家遇到百萬(wàn)級(jí)千萬(wàn)級(jí)數(shù)據(jù)的時(shí)候,大家就可能開(kāi)始添加表分區(qū)了。so,我就開(kāi)始了我的分(keng)區(qū)(die)之旅。一開(kāi)始,由于我的這張大表有100多萬(wàn)數(shù)據(jù)量,就單單一個(gè)存儲(chǔ)過(guò)程居然執(zhí)行了一個(gè)多鐘,于是,我便把這張大表改成分區(qū)表,并在ID上給這添加索引,優(yōu)化存儲(chǔ)過(guò)程。改成分區(qū)表之后,效果果然斐然,從1個(gè)多鐘優(yōu)化到了一分半鐘。可惜啊,好景不長(zhǎng),才過(guò)了2天,測(cè)試姐姐就把我啦過(guò)去看問(wèn)題,說(shuō)我的存儲(chǔ)過(guò)程把整個(gè)過(guò)程卡住了,700多萬(wàn)的數(shù)據(jù),存儲(chǔ)過(guò)程居然執(zhí)行了將近4個(gè)小時(shí)沒(méi)執(zhí)行完,我嘴上笑嘻嘻,心里媽賣批。自己挖的坑,含著淚也要把它搞定。我首先查了下是不是分區(qū)表的索引失效了,但經(jīng)過(guò)排查,發(fā)現(xiàn)并不是(心中一萬(wàn)頭草擬馬跑過(guò)),然后,我就執(zhí)行一樂(lè)該id下的700多萬(wàn)數(shù)據(jù)的存儲(chǔ)過(guò)程,果然很慢,難怪他被卡死了,一查下去發(fā)現(xiàn)是select語(yǔ)句查詢很慢,奇怪點(diǎn)就在當(dāng)我用另一個(gè)也是擁有700多萬(wàn)的id數(shù)據(jù)執(zhí)行存儲(chǔ)過(guò)程的時(shí)候,奇跡發(fā)現(xiàn)了,居然3分多鐘就完成。為什么同樣是700多萬(wàn)的數(shù)據(jù),一個(gè)執(zhí)行了4個(gè)多鐘還沒(méi)完成,一個(gè)執(zhí)行了3分多鐘就完成了。抱著疑問(wèn),我一步一步排查這個(gè)分區(qū)表下不同id表有什么區(qū)別呢,最終發(fā)現(xiàn)執(zhí)行快的id,在該分區(qū)表下global_stats=YES,而另一個(gè)的global_stats則=false。于是我查到了以下的信息"分區(qū)表里global_stats=YES的全局統(tǒng)計(jì)信息是否準(zhǔn)確關(guān)系到optimizer能否選擇較優(yōu)的執(zhí)行計(jì)劃,對(duì)分區(qū)表執(zhí)行全局統(tǒng)計(jì)會(huì)不可避免的產(chǎn)生FTS加重系統(tǒng)負(fù)擔(dān),尤其對(duì)于DW環(huán)境里規(guī)模較大的分區(qū)表而言更是如此。"而global_stats這個(gè)代表該分區(qū)表是否對(duì)該分區(qū)進(jìn)行了統(tǒng)計(jì)分析,一般情況下,系統(tǒng)在不知道什么時(shí)候都會(huì)對(duì)這分區(qū)就行統(tǒng)計(jì)分析的。而對(duì)這個(gè)分區(qū)進(jìn)行統(tǒng)計(jì)分析又包含了兩種方式,非incremental方式,incremental方式,而非incremental方式會(huì)進(jìn)行全量掃描分區(qū)表中所有的分區(qū),incremental方式則會(huì)增量掃描分區(qū)表中的分區(qū)。incremental statistics collect正是在這一背景下應(yīng)運(yùn)而生,簡(jiǎn)單的說(shuō)incremental statistics collect會(huì)實(shí)時(shí)記錄分區(qū)表里每個(gè)partition每列值的更新情況,這一信息保存在SYSAUX表空間里,后續(xù)根據(jù)這一信息在執(zhí)行全局統(tǒng)計(jì)時(shí)僅會(huì)針對(duì)有變化的partition進(jìn)行statistics collect,并將收集的結(jié)果與沒(méi)有變化過(guò)的partition原有的統(tǒng)計(jì)信息進(jìn)行整合,計(jì)算出準(zhǔn)確的global stats,省去了必須去掃描每一個(gè)partition的步驟。非incremental方式下新加分區(qū)后對(duì)整個(gè)分區(qū)表收集統(tǒng)計(jì)信息,會(huì)全量掃描分區(qū)表中所有的分區(qū),即使那些沒(méi)有改變過(guò)的分區(qū)也會(huì)被重新掃描一遍 ------------------------------------------------------------------------ 深入學(xué)習(xí)Oracle分區(qū)表及分區(qū)索引關(guān)于分區(qū)表和分區(qū)索引(About Partitioned Tables and Indexes)對(duì)于10gR2而言,基本上可以分成幾類:?    Range(范圍)分區(qū)?    Hash(哈希)分區(qū)?    List(列表)分區(qū)?    以及組合分區(qū):Range-Hash,Range-List。對(duì)于表而言(常規(guī)意義上的堆組織表),上述分區(qū)形式都可以應(yīng)用(甚至可以對(duì)某個(gè)分區(qū)指定compress屬性),只不過(guò)分區(qū)依賴列不能是lob,long之類數(shù)據(jù)類型,每個(gè)表的分區(qū)或子分區(qū)數(shù)的總數(shù)不能超過(guò)1023個(gè)。對(duì)于索引組織表,只能夠支持普通分區(qū)方式,不支持組合分區(qū),常規(guī)表的限制對(duì)于索引組織表同樣有效,除此之外呢,還有一些其實(shí)的限制,比如要求索引組織表的分區(qū)依賴列必須是主鍵才可以等。注:本篇所有示例僅針對(duì)常規(guī)表,即堆組織表!對(duì)于索引,需要區(qū)分創(chuàng)建的是全局索引,或本地索引:l 全局索引(global index):即可以分區(qū),也可以不分區(qū)。即可以建range分區(qū),也可以建hash分區(qū),即可建于分區(qū)表,又可創(chuàng)建于非分區(qū)表上,就是說(shuō),全局索引是完全獨(dú)立的,因此它也需要我們更多的維護(hù)操作。l 本地索引(local index):其分區(qū)形式與表的分區(qū)完全相同,依賴列相同,存儲(chǔ)屬性也相同。對(duì)于本地索引,其索引分區(qū)的維護(hù)自動(dòng)進(jìn)行,就是說(shuō)你add/drop/split/truncate表的分區(qū)時(shí),本地索引會(huì)自動(dòng)維護(hù)其索引分區(qū)。Oracle建議如果單個(gè)表超過(guò)2G就最好對(duì)其進(jìn)行分區(qū),對(duì)于大表創(chuàng)建分區(qū)的好處是顯而易見(jiàn)的,這里不多論述why,而將重點(diǎn)放在when以及how。ORACLE對(duì)于分區(qū)表方式其實(shí)就是將表分段存儲(chǔ),一般普通表格是一個(gè)段存 儲(chǔ),而分區(qū)表會(huì)分成多個(gè)段,所以查找數(shù)據(jù)過(guò)程都是先定位根據(jù)查詢條件定位分區(qū)范圍,即數(shù)據(jù)在那個(gè)分區(qū)或那幾個(gè)內(nèi)部,然后在分區(qū)內(nèi)部去查找數(shù)據(jù),一個(gè)分區(qū)一 般保證四十多萬(wàn)條數(shù)據(jù)就比較正常了,但是分區(qū)表并非亂建立,而其維護(hù)性也相對(duì)較為復(fù)雜一點(diǎn),而索引的創(chuàng)建也是有點(diǎn)講究的,這些以下盡量闡述詳細(xì)即可。range分區(qū)方式,也算是最常用的分區(qū)方式,其通過(guò)某字段或幾個(gè)字段的組合的值,從小到大,按照指定的范圍說(shuō)明進(jìn)行分區(qū),我們?cè)贗NSERT數(shù)據(jù)的時(shí)候就會(huì)存儲(chǔ)到指定的分區(qū)中。List分區(qū)方式,一般是在range基礎(chǔ)上做的二級(jí)分區(qū)較多,是一種列舉方式進(jìn)行分區(qū),一般講某些地區(qū)、狀態(tài)或指定規(guī)則的編碼等進(jìn)行劃分。Hash分區(qū)方式,它沒(méi)有固定的規(guī)則,由ORACLE管理,只需要將值INSERT進(jìn)去,ORACLE會(huì)自動(dòng)去根據(jù)一套HASH算法去劃分分區(qū),只需要告訴ORACLE要分幾個(gè)區(qū)即可。WHEN一、When使用Range分區(qū)Range分區(qū)呢是應(yīng)用范圍比較廣的表分區(qū)方式,它是以列的值的范圍來(lái)做為分區(qū)的劃分條件,將記錄存放到列值所在的range分區(qū)中,比如按照 時(shí)間劃分,2008年1季度的數(shù)據(jù)放到a分區(qū),08年2季度的數(shù)據(jù)放到b分區(qū),因此在創(chuàng)建的時(shí)候呢,需要你指定基于的列,以及分區(qū)的范圍值,如果某些記錄 暫無(wú)法預(yù)測(cè)范圍,可以創(chuàng)建maxvalue分區(qū),所有不在指定范圍內(nèi)的記錄都會(huì)被存儲(chǔ)到maxvalue所在分區(qū)中,并且支持指定多列做為依賴列,后面在 講how的時(shí)候會(huì)詳細(xì)談到。二、When使用Hash分區(qū)通常呢,對(duì)于那些無(wú)法有效劃分范圍的表,可以使用hash分區(qū),這樣對(duì)于提高性能還是會(huì)有一定的幫助。hash分區(qū)會(huì)將表中的數(shù)據(jù)平均分配到你 指定的幾個(gè)分區(qū)中,列所在分區(qū)是依據(jù)分區(qū)列的hash值自動(dòng)分配,因此你并不能控制也不知道哪條記錄會(huì)被放到哪個(gè)分區(qū)中,hash分區(qū)也可以支持多個(gè)依賴 列。三、When使用List分區(qū)List分區(qū)與range分區(qū)和hash分區(qū)都有類似之處,該分區(qū)與range分區(qū)類似的是也需要你指定列的值,但這又不同與range分區(qū)的 范圍式列值---其分區(qū)值必須明確指定,也不同與hash分區(qū)---通過(guò)明確指定分區(qū)值,你能控制記錄存儲(chǔ)在哪個(gè)分區(qū)。它的分區(qū)列只能有一個(gè),而不能像 range或者h(yuǎn)ash分區(qū)那樣同時(shí)指定多個(gè)列做為分區(qū)依賴列,不過(guò)呢,它的單個(gè)分區(qū)對(duì)應(yīng)值可以是多個(gè)。你在分區(qū)時(shí)必須確定分區(qū)列可能存在的值,一旦插入的列值不在分區(qū)范圍內(nèi),則插入/更新就會(huì)失敗,因此通常建議使用list分區(qū)時(shí),要?jiǎng)?chuàng)建一個(gè)default分區(qū)存儲(chǔ)那些不在指定范圍內(nèi)的記錄,類似range分區(qū)中的maxvalue分區(qū)。四、When使用組合分區(qū)如果某表按照某列分區(qū)之后,仍然較大,或者是一些其它的需求,還可以通過(guò)分區(qū)內(nèi)再建子分區(qū)的方式將分區(qū)再分區(qū),即組合分區(qū)的方式。組合分區(qū)呢在10g中有兩種:range-hash,range-list。注意順序喲,根分區(qū)只能是range分區(qū),子分區(qū)可以是hash分區(qū)或list分區(qū)。提示:11g在組合分區(qū)功能這塊有所增強(qiáng),又推出了range-range,list-range,list-list,list-hash, 這就相當(dāng)于除hash外三種分區(qū)方式的笛卡爾形式都有了。為什么會(huì)沒(méi)有hash做為根分區(qū)的組合分區(qū)形式呢,再仔細(xì)回味一下第二點(diǎn),你一定能夠想明 白~~。深入學(xué)習(xí)Oracle分區(qū)表及分區(qū)索引(2)一、如何創(chuàng)建如果想對(duì)某個(gè)表做分區(qū),必須在創(chuàng)建表時(shí)就指定分區(qū),我們可以對(duì)一個(gè)包含分區(qū)的表中的分區(qū)做修改,但不能直接將一個(gè)未分區(qū)的表修改成分區(qū)表(起碼在10g是不行的,當(dāng)然你可能會(huì)說(shuō),可以通過(guò)在線重定義的方式,但是這不是直接喲,這也是借助臨時(shí)表間接實(shí)現(xiàn)的)。創(chuàng)建表或索引的語(yǔ)法就不說(shuō)了,大家肯定比我還熟悉,而想在建表(索引)同時(shí)指定分區(qū)也非常容易,只需要把創(chuàng)建分區(qū)的子句放到";"前就行啦,同 時(shí)需要注意表的row movement屬性,它用來(lái)控制是否允許修改列值所造成的記錄移動(dòng)至其它分區(qū)存儲(chǔ),有enable|disable兩種狀態(tài),默認(rèn)是disable row movement,當(dāng)disable時(shí),如果記錄要被更新至其它分區(qū),則更新語(yǔ)句會(huì)報(bào)錯(cuò)。下面分別演示不同分區(qū)方式的表和索引的創(chuàng)建:1、創(chuàng)建range分區(qū)語(yǔ)法如下,需要我們指定的有:l column:分區(qū)依賴列(如果是多個(gè),以逗號(hào)分隔);l partition:分區(qū)名稱;l values less than:后跟分區(qū)范圍值(如果依賴列有多個(gè),范圍對(duì)應(yīng)值也應(yīng)是多個(gè),中間以逗號(hào)分隔);l tablespace_clause:分區(qū)的存儲(chǔ)屬性,例如所在表空間等屬性(可為空),默認(rèn)繼承基表所在表空間的屬性。① 創(chuàng)建一個(gè)標(biāo)準(zhǔn)的range分區(qū)表:JSSWEB> create table t_partition_range (id number,name varchar2(50))partition by range(id)(partition t_range_p1 values less than (10) tablespace tbspart01,partition t_range_p2 values less than (20) tablespace tbspart02,partition t_range_p3 values less than (30) tablespace tbspart03,partition t_range_pmax values less than (maxvalue) tablespace tbspart04);表已創(chuàng)建。要查詢創(chuàng)建分區(qū)的信息,可以通過(guò)查詢user_part_tables,user_tab_partitions兩個(gè)數(shù)據(jù)字典(索引分區(qū)、組織分區(qū)等信息也有對(duì)應(yīng)的數(shù)據(jù)字典,后續(xù)示例會(huì)逐步提及)。user_part_tables:記錄分區(qū)的表的信息;user_tab_partitions:記錄表的分區(qū)的信息。例如:JSSWEB> select table_name,partitioning_type,partition_countFrom user_part_tables where table_name='T_PARTITION_RANGE';JSSWEB> select partition_name,high_value,tablespace_namefrom user_tab_partitions where table_name='T_PARTITION_RANGE'order by partition_position;② 創(chuàng)建global索引range分區(qū):JSSWEB> create index idx_parti_range_id on t_partition_range(id)2 global partition by range(id)(3 partition i_range_p1 values less than (10) tablespace tbspart01,4 partition i_range_p2 values less than (40) tablespace tbspart02,5 partition i_range_pmax values less than (maxvalue) tablespace tbspart03);索引已創(chuàng)建。由上例可以看出,創(chuàng)建global索引的分區(qū)與創(chuàng)建表的分區(qū)語(yǔ)句格式完全相同,而且其分區(qū)形式與索引所在表的分區(qū)形式?jīng)]有關(guān)聯(lián)關(guān)系。注意:我們這里借助上面的表t_partition_range來(lái)演示創(chuàng)建range分區(qū)的global索引,并不表示range分區(qū)的表,只能創(chuàng)建range分區(qū)的global索引,只要你想,也可以為其創(chuàng)建hash分區(qū)的global索引。查詢索引的分區(qū)信息可以通過(guò)user_part_indexes、user_ind_partitions兩個(gè)數(shù)據(jù)字典:JSSWEB> select index_name, partitioning_type, partition_count2 From user_part_indexes3 where index_name = 'IDX_PARTI_RANGE_ID';③ Local分區(qū)索引的創(chuàng)建最簡(jiǎn)單,例如:仍然借助t_partition_range表來(lái)創(chuàng)建索引--首先刪除之前創(chuàng)建的global索引JSSWEB> drop index IDX_PARTI_RANGE_ID;索引已刪除。JSSWEB> create index IDX_PARTI_RANGE_ID on T_PARTITION_RANGE(id) local;索引已創(chuàng)建。查詢相關(guān)數(shù)據(jù)字典:JSSWEB> select index_name, partitioning_type, partition_count2 From user_part_indexes3 where index_name = 'IDX_PARTI_RANGE_ID';JSSWEB> select partition_name, high_value, tablespace_name2 from user_ind_partitions3 where index_name = 'IDX_PARTI_RANGE_ID'4 order by partition_position;可以看出,local索引的分區(qū)完全繼承表的分區(qū)的屬性,包括分區(qū)類型,分區(qū)的范圍值即不需指定也不能更改,這就是前面說(shuō)的:local索引的分區(qū)維護(hù)完全依賴于其索引所在表。不過(guò)呢分區(qū)名稱,以及分區(qū)所在表空間等信息是可以自定義的,例如:SQL> create index IDX_PART_RANGE_ID ON T_PARTITION_RANGE(id) local (2 partition i_range_p1 tablespace tbspart01,3 partition i_range_p2 tablespace tbspart01,4 partition i_range_p3 tablespace tbspart02,5 partition i_range_pmax tablespace tbspart026 );索引已創(chuàng)建。SQL> select index_name, partitioning_type, partition_count2 From user_part_indexes3 where index_name = 'IDX_PART_RANGE_ID';SQL> select partition_name, high_value, tablespace_name2 from user_ind_partitions3 where index_name = 'IDX_PART_RANGE_ID'4 order by partition_position;創(chuàng)建hash分區(qū)語(yǔ)法如下:[圖:hash_partitioning.gif]語(yǔ)法看起來(lái)比range復(fù)雜,其實(shí)使用起來(lái)比range更簡(jiǎn)單,這里需要我們指定的有:l column:分區(qū)依賴列(支持多個(gè),中間以逗號(hào)分隔);l partition:指定分區(qū),有兩種方式:n 直接指定分區(qū)名,分區(qū)所在表空間等信息n 只指定分區(qū)數(shù)量,和可供使用的表空間。2、創(chuàng)建hash分區(qū)JSSWEB> create table t_partition_hash (id number,name varchar2(50))2 partition by hash(id)(3 partition t_hash_p1 tablespace tbspart01,4 partition t_hash_p2 tablespace tbspart02,5 partition t_hash_p3 tablespace tbspart03);表已創(chuàng)建。要實(shí)現(xiàn)同樣效果,你還可以這樣:JSSWEB> create table t_partition_hash2 (id number,name varchar2(50))2 partition by hash(id)3 partitions 3 store in(tbspart01,tbspart02,tbspart03);表已創(chuàng)建。這就是上面說(shuō)的,直接指定分區(qū)數(shù)量和可供使用的表空間。提示:這里分區(qū)數(shù)量和可供使用的表空間數(shù)量之間沒(méi)有直接對(duì)應(yīng)關(guān)系。分區(qū)數(shù)并不一定要等于表空間數(shù)。要查詢表的分區(qū)信息,仍然是通過(guò)user_part_tables,user_tab_partitions兩個(gè)數(shù)據(jù)字典,這里不再舉例。① Global索引hash分區(qū)Hash分區(qū)索引的子句與hash分區(qū)表的創(chuàng)建子句完全相同,例如:JSSWEB> create index idx_part_hash_id on t_partition_hash(id)2 global partition by hash(id)3 partitions 3 store in(tbspart01,tbspart02,tbspart03);索引已創(chuàng)建。查詢索引的分區(qū)信息也仍是通過(guò)user_part_indexes、user_ind_partitions兩個(gè)數(shù)據(jù)字典,不再舉例。② 創(chuàng)建Local索引在前面學(xué)習(xí)range分區(qū)時(shí),我們已經(jīng)對(duì)Local索引的特性做了非常清晰的概述,因此這里也不再舉例,如有疑問(wèn),建議再仔細(xì)復(fù)習(xí)range分區(qū)的相關(guān)示例,如果還有疑問(wèn),當(dāng)面問(wèn)我好了:)綜上:? 對(duì)于global索引分區(qū)而言,在10g中只能支持range分區(qū)和hash分區(qū),因此后續(xù)示例中不會(huì)再提及。? 對(duì)于local索引分區(qū)而言,其分區(qū)形式完全依賴于索引所在表的分區(qū)形式,不管從創(chuàng)建語(yǔ)法還是理解難度均無(wú)技術(shù)含量,因此后續(xù)也不再提供示例。? 注意,在創(chuàng)建索引時(shí)如果不顯式指定global或local,則默認(rèn)是global。? 注意,在創(chuàng)建global索引時(shí)如果不顯式指定分區(qū)子句,則默認(rèn)不分區(qū)(廢話)。3、分區(qū)應(yīng)用: 一般一張表超過(guò)2G的大小,ORACLE是推薦使用分區(qū)表的,分區(qū)一般都需要 創(chuàng)建索引,說(shuō)到分區(qū)索引,就可以分為:全局索引、分區(qū)索引,即:global索引和local索引,前者為默認(rèn)情況下在分區(qū)表上創(chuàng)建索引時(shí)的索引方式,并 不對(duì)索引進(jìn)行分區(qū)(索引也是表結(jié)構(gòu),索引大了也需要分區(qū),關(guān)于索引以后專門寫點(diǎn))而全局索引可修飾為分區(qū)索引,但是和local索引有所區(qū)別,前者的分區(qū) 方式完全按照自定義方式去創(chuàng)建,和表結(jié)構(gòu)完全無(wú)關(guān),所以對(duì)于分區(qū)表的全局索引有以下兩幅網(wǎng)上常用的圖解:3.1、對(duì)于分區(qū)表的不分區(qū)索引(這個(gè)有點(diǎn)繞,不過(guò)就是表分區(qū),但其索引不分區(qū)):創(chuàng)建語(yǔ)法(直接創(chuàng)建即可):CREATE INDEX ON ();3.2、對(duì)于分區(qū)表的分區(qū)索引:創(chuàng)建語(yǔ)法為:CREATE INDEX INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1)GLOBAL PARTITION BY RANGE(COL1)(PARTITION IDX_P1 values less than (1000000),PARTITION IDX_P2 values less than (2000000),PARTITION IDX_P3 values less than (MAXVALUE));3.3、LOCAL索引結(jié)構(gòu):創(chuàng)建語(yǔ)法為:CREATE INDEX INX_TAB_PARTITION_COL1 ON TABLE_PARTITION(COL1) LOCAL;也可按照分區(qū)表的的分區(qū)結(jié)構(gòu)給與一一定義,索引的分區(qū)將得到重命名。分區(qū)上的位圖索引只能為L(zhǎng)OCAL索引,不能為GLOBAL全局索引。3.4、對(duì)比索引方式:一般使用LOCAL索引較為方便,而且維護(hù)代價(jià)較低,并且LOCAL索引是在分區(qū)的基礎(chǔ)上去創(chuàng)建索引,類似于在一個(gè)子表內(nèi)部去創(chuàng)建索引,這樣開(kāi)銷主要是區(qū) 分分區(qū)上,很規(guī)范的管理起來(lái),在OLAP系統(tǒng)中應(yīng)用很廣泛;而相對(duì)的GLOBAL索引是全局類型的索引,根據(jù)實(shí)際情況可以調(diào)整分區(qū)的類別,而并非按照分區(qū) 結(jié)構(gòu)一一定義,相對(duì)維護(hù)代價(jià)較高一些,在OLTP環(huán)境用得相對(duì)較多,這里所謂OLTP和OLAP也是相對(duì)的,不是特殊的項(xiàng)目,沒(méi)有絕對(duì)的劃分概念,在應(yīng)用 過(guò)程中依據(jù)實(shí)際情況而定,來(lái)提高整體的運(yùn)行性能。4、常用視圖: 1、查詢當(dāng)前用戶下有哪些是分區(qū)表:SELECT * FROM USER_PART_TABLES;2、查詢當(dāng)前用戶下有哪些分區(qū)索引:SELECT * FROM USER_PART_INDEXES;3、查詢當(dāng)前用戶下分區(qū)索引的分區(qū)信息:SELECT * FROM USER_IND_PARTITIONS TWHERE T.INDEX_NAME=?4、查詢當(dāng)前用戶下分區(qū)表的分區(qū)信息:SELECT * FROM USER_TAB_PARTITIONS TWHERE T.TABLE_NAME=?;5、查詢某分區(qū)下的數(shù)據(jù)量:SELECT COUNT(*) FROM TABLE_PARTITION PARTITION(TAB_PARTOTION_01);6、查詢索引、表上在那些列上創(chuàng)建了分區(qū):SELECT * FROM USER_PART_KEY_COLUMNS;7、查詢某用戶下二級(jí)分區(qū)的信息(只有創(chuàng)建了二級(jí)分區(qū)才有數(shù)據(jù)):SELECT * FROM USER_TAB_SUBPARTITIONS;5、維護(hù)操作: 5.1、刪除分區(qū)ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03;如果是全局索引,因?yàn)槿炙饕姆謪^(qū)結(jié)構(gòu)和表可以不一致,若不一致的情況下,會(huì)導(dǎo)致整個(gè)全局索引失效,在刪除分區(qū)的時(shí)候,語(yǔ)句修改為:ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_03 UPDATE GLOBAL INDEXES;5.2、分區(qū)合并(從中間刪除掉一個(gè)分區(qū),或者兩個(gè)分區(qū)需要合并后減少分區(qū)數(shù)量)合并分區(qū)和刪除中間的RANGE有點(diǎn)像,但是合并分區(qū)是不會(huì)刪除數(shù)據(jù)的,對(duì)于LIST、HASH分區(qū)也是和RANGE分區(qū)不一樣的,其語(yǔ)法為:ALTER TABLE TABLE_PARTITION MERGE PARTITIONS TAB_PARTOTION_01,TAB_PARTOTION_02 INTO PARTITION MERGED_PARTITION;5.3、分隔分區(qū)(一般分區(qū)從擴(kuò)展分區(qū)從分隔) ALTER TABLE TABLE_PARTITION SPLIT PARTITION TAB_PARTOTION_OTHERE AT(2500000)INTO (PARTITION TAB_PARTOTION_05,PARTITION TAB_PARTOTION_OTHERE);5.4、創(chuàng)建新的分區(qū)(分區(qū)數(shù)據(jù)若不能提供范圍,則插入時(shí)會(huì)報(bào)錯(cuò),需要增加分區(qū)來(lái)擴(kuò)大范圍) 一般有擴(kuò)展分區(qū)的是都是用分隔的方式,若上述創(chuàng)建表時(shí)沒(méi)有創(chuàng)建TAB_PARTOTION_OTHER分區(qū)時(shí),在插入數(shù)據(jù)較大時(shí)(按照上述建立規(guī)則,超過(guò)1800000就應(yīng)該創(chuàng)建新的分區(qū)來(lái)存儲(chǔ)),就可以創(chuàng)建新的分區(qū),如:為了試驗(yàn),我們將擴(kuò)展分區(qū)先刪除掉再創(chuàng)建新的分區(qū)(因?yàn)镺RACLE要求,分區(qū)的數(shù)據(jù)不允許重疊,即按照分區(qū)字段同樣的數(shù)據(jù)不能同時(shí)存儲(chǔ)在不同的分區(qū)中):ALTER TABLE TABLE_PARTITION DROP PARTITION TAB_PARTOTION_OTHER;ALTER TABLE TABLE_PARTITION ADD PARTITION TAB_PARTOTION_06 VALUES LESS THAN(2500000);在分區(qū)下創(chuàng)建新的子分區(qū)大致如下(RANGE分區(qū),若為L(zhǎng)IST或HASH分區(qū),將創(chuàng)建方式修改為對(duì)應(yīng)的方式即可):ALTER TABLE MODIFY PARTITION ADD SUBPARTITION VALUES LESS THAN(....);5.5、修改分區(qū)名稱(修改相關(guān)的屬性信息) ALTER TABLE TABLE_PARTITION RENAME PARTITION MERGED_PARTITION TO MERGED_PARTITION02;5.6、交換分區(qū)(快速交換數(shù)據(jù),其實(shí)是交換段名稱指針)首先創(chuàng)建一個(gè)交換表,和原表結(jié)構(gòu)相同,如果有數(shù)據(jù),必須符合所交換對(duì)應(yīng)分區(qū)的條件:CREATE TABLE TABLE_PARTITION_2AS SELECT * FROM TABLE_PARTITION WHERE 1=2;然后將第一個(gè)分區(qū)的數(shù)據(jù)交換出去:ALTER TABLE TABLE_PARTITION EXCHANGE PARTITION TAB_PARTOTION_01WITH TABLE TABLE_PARTITION_2 INCLUDING INDEXES;此時(shí)會(huì)發(fā)現(xiàn)第一個(gè)分區(qū)的數(shù)據(jù)和表TABLE_PARTITION_2做了瞬間交換,比TRUNCATE還要快,因?yàn)檫@個(gè)過(guò)程沒(méi)有進(jìn)行數(shù)據(jù)轉(zhuǎn)存,只是段名稱的修改過(guò)程,和實(shí)際的數(shù)據(jù)量沒(méi)有關(guān)系。如果是子分區(qū)也可以與外部的表進(jìn)行交換,只需要將關(guān)鍵字修改為:SUBPARTITION 即可。5.7、清空分區(qū)數(shù)據(jù)ALTER TABLE TRUNCATE PARTITION ;ALTER TABLE TRUNCATE subpartition ;6、磁盤碎片壓縮對(duì)分區(qū)表的某分區(qū)進(jìn)行磁盤壓縮,當(dāng)對(duì)分區(qū)內(nèi)部數(shù)據(jù)進(jìn)行了大量的UPDATE、DELETE操作后,一定時(shí)間需要進(jìn)行磁盤壓縮,否則在查詢時(shí),若通過(guò)FULL SCAN掃描數(shù)據(jù),將會(huì)把空塊也會(huì)掃描到,對(duì)表進(jìn)行磁盤壓縮需要進(jìn)行行遷移操作,所以首先需要操作:ALTER TABLE ENABLE ROW MOVEMENT ;對(duì)分區(qū)表的某分區(qū)壓縮語(yǔ)法為:ALTER TABLEmodify partition shrink space;對(duì)普通表壓縮:ALTER TABLE shrink space;對(duì)于索引也需要進(jìn)行壓縮,索引也是表:ALTER INDEX shrink space; ---------------------------------------------------------------------------------------- oracle表空間表分區(qū)詳解及oracle表分區(qū)查詢使用方法(轉(zhuǎn)+整理) 此文從以下幾個(gè)方面來(lái)整理關(guān)于分區(qū)表的概念及操作:1.表空間及分區(qū)表的概念 2.表分區(qū)的具體作用 3.表分區(qū)的優(yōu)缺點(diǎn) 4.表分區(qū)的幾種類型及操作方法 5.對(duì)表分區(qū)的維護(hù)性操作.表空間及分區(qū)表的概念 表空間:是一個(gè)或多個(gè)數(shù)據(jù)文件的集合,所有的數(shù)據(jù)對(duì)象都存放在指定的表空間中,但主要存放的是表, 所以稱作表空間。 分區(qū)表:當(dāng)表中的數(shù)據(jù)量不斷增大,查詢數(shù)據(jù)的速度就會(huì)變慢,應(yīng)用程序的性能就會(huì)下降,這時(shí)就應(yīng)該考慮對(duì)表進(jìn)行分區(qū)。表進(jìn)行分區(qū)后,邏輯上表仍然是一張完整的表,只是將表中的數(shù)據(jù)在物理上存放到多個(gè)表空間(物理文件上),這樣查詢數(shù)據(jù)時(shí),不至于每次都掃描整張表。表分區(qū)的具體作用 Oracle的表分區(qū)功能通過(guò)改善可管理性、性能和可用性,從而為各式應(yīng)用程序帶來(lái)了極大的好處。通常,分區(qū)可以使某些查詢以及維護(hù)操作的性能大大提高。此外,分區(qū)還可以極大簡(jiǎn)化常見(jiàn)的管理任務(wù),分區(qū)是構(gòu)建千兆字節(jié)數(shù)據(jù)系統(tǒng)或超高可用性系統(tǒng)的關(guān)鍵工具。分區(qū)功能能夠?qū)⒈?、索引或索引組織表進(jìn)一步細(xì)分為段,這些數(shù)據(jù)庫(kù)對(duì)象的段叫做分區(qū)。每個(gè)分區(qū)有自己的名稱,還可以選擇自己的存儲(chǔ)特性。從數(shù)據(jù)庫(kù)管理員的角度來(lái)看,一個(gè)分區(qū)后的對(duì)象具有多個(gè)段,這些段既可進(jìn)行集體管理,也可單獨(dú)管理,這就使數(shù)據(jù)庫(kù)管理員在管理分區(qū)后的對(duì)象時(shí)有相當(dāng)大的靈活性。但是,從應(yīng)用程序的角度來(lái)看,分區(qū)后的表與非分區(qū)表完全相同,使用 SQL DML 命令訪問(wèn)分區(qū)后的表時(shí),無(wú)需任何修改。什么時(shí)候使用分區(qū)表:表的大小超過(guò)2GB。 表中包含歷史數(shù)據(jù),新的數(shù)據(jù)被增加都新的分區(qū)中。 表分區(qū)的優(yōu)缺點(diǎn) 表分區(qū)有以下優(yōu)點(diǎn):改善查詢性能:對(duì)分區(qū)對(duì)象的查詢可以僅搜索自己關(guān)心的分區(qū),提高檢索速度。 增強(qiáng)可用性:如果表的某個(gè)分區(qū)出現(xiàn)故障,表在其他分區(qū)的數(shù)據(jù)仍然可用; 維護(hù)方便:如果表的某個(gè)分區(qū)出現(xiàn)故障,需要修復(fù)數(shù)據(jù),只修復(fù)該分區(qū)即可; 均衡I/O:可以把不同的分區(qū)映射到磁盤以平衡I/O,改善整個(gè)系統(tǒng)性能。 缺點(diǎn):已經(jīng)存在的表沒(méi)有方法可以直接轉(zhuǎn)化為分區(qū)表。但是有幾種方式可以間接完成這個(gè)操作,大家可以參考:oracle分區(qū)表的建立方法(包含已經(jīng)存在的表要分區(qū)):http://blog.csdn.net/wanglilin/article/details/7177338 表分區(qū)的幾種類型及操作方法 范圍分區(qū): 范圍分區(qū)將數(shù)據(jù)基于范圍映射到每一個(gè)分區(qū),這個(gè)范圍是你在創(chuàng)建分區(qū)時(shí)指定的分區(qū)鍵決定的。這種分區(qū)方式是最為常用的,并且分區(qū)鍵經(jīng)常采用日期。舉個(gè)例子:你可能會(huì)將銷售數(shù)據(jù)按照月份進(jìn)行分區(qū)。 當(dāng)使用范圍分區(qū)時(shí),請(qǐng)考慮以下幾個(gè)規(guī)則:1、每一個(gè)分區(qū)都必須有一個(gè)VALUES LESS THEN子句,它指定了一個(gè)不包括在該分區(qū)中的上限值。分區(qū)鍵的任何值等于或者大于這個(gè)上限值的記錄都會(huì)被加入到下一個(gè)高一些的分區(qū)中。 2、所有分區(qū),除了第一個(gè),都會(huì)有一個(gè)隱式的下限值,這個(gè)值就是此分區(qū)的前一個(gè)分區(qū)的上限值。 3、在最高的分區(qū)中,MAXVALUE被定義。MAXVALUE代表了一個(gè)不確定的值。這個(gè)值高于其它分區(qū)中的任何分區(qū)鍵的值,也可以理解為高于任何分區(qū)中指定的VALUE LESS THEN的值,同時(shí)包括空值。例一:假設(shè)有一個(gè)CUSTOMER表,表中有數(shù)據(jù)200000行,我們將此表通過(guò)CUSTOMER_ID進(jìn)行分區(qū),每個(gè)分區(qū)存儲(chǔ)100000行,我們將每個(gè)分區(qū)保存到單獨(dú)的表空間中,這樣數(shù)據(jù)文件就可以跨越多個(gè)物理磁盤。下面是創(chuàng)建表和分區(qū)的代碼,如下:CREATE TABLE CUSTOMER ( CUSTOMER_ID NUMBER NOT NULL PRIMARY KEY, FIRST_NAME VARCHAR2(30) NOT NULL, LAST_NAME VARCHAR2(30) NOT NULL, PHONEVARCHAR2(15) NOT NULL, EMAILVARCHAR2(80), STATUS CHAR(1) ) PARTITION BY RANGE (CUSTOMER_ID) ( PARTITION CUS_PART1 VALUES LESS THAN (100000) TABLESPACE CUS_TS01, PARTITION CUS_PART2 VALUES LESS THAN (200000) TABLESPACE CUS_TS02 ) 例二:按時(shí)間劃分CREATE TABLE ORDER_ACTIVITIES ( ORDER_ID NUMBER(7) NOT NULL, ORDER_DATE DATE, TOTAL_AMOUNT NUMBER, CUSTOTMER_ID NUMBER(7), PAID CHAR(1) ) PARTITION BY RANGE (ORDER_DATE) ( PARTITION ORD_ACT_PART01 VALUES LESS THAN (TO_DATE('01- MAY -2003','DD-MON-YYYY')) TABLESPACEORD_TS01, PARTITION ORD_ACT_PART02 VALUES LESS THAN (TO_DATE('01-JUN-2003','DD-MON-YYYY')) TABLESPACE ORD_TS02, PARTITION ORD_ACT_PART02 VALUES LESS THAN (TO_DATE('01-JUL-2003','DD-MON-YYYY')) TABLESPACE ORD_TS03 ) 例三:MAXVALUECREATE TABLE RangeTable ( idd INT PRIMARY KEY , iNAME VARCHAR(10), grade INT ) PARTITION BY RANGE (grade) ( PARTITION part1 VALUES LESS THEN (1000) TABLESPACE Part1_tb, PARTITION part2 VALUES LESS THEN (MAXVALUE) TABLESPACE Part2_tb ); 列表分區(qū): 該分區(qū)的特點(diǎn)是某列的值只有幾個(gè),基于這樣的特點(diǎn)我們可以采用列表分區(qū)。例一CREATE TABLE PROBLEM_TICKETS ( PROBLEM_ID NUMBER(7) NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR2(2000), CUSTOMER_ID NUMBER(7) NOT NULL, DATE_ENTERED DATE NOT NULL, STATUS VARCHAR2(20) ) PARTITION BY LIST (STATUS) ( PARTITION PROB_ACTIVE VALUES ('ACTIVE') TABLESPACE PROB_TS01, PARTITION PROB_INACTIVE VALUES ('INACTIVE') TABLESPACE PROB_TS02 ) 例二CREATE TABLE ListTable ( id INT PRIMARY KEY , name VARCHAR (20), area VARCHAR (10) ) PARTITION BY LIST (area) ( PARTITION part1 VALUES ('guangdong','beijing') TABLESPACE Part1_tb, PARTITION part2 VALUES ('shanghai','nanjing') TABLESPACE Part2_tb ); ) 散列分區(qū): 這類分區(qū)是在列值上使用散列算法,以確定將行放入哪個(gè)分區(qū)中。當(dāng)列的值沒(méi)有合適的條件時(shí),建議使用散列分區(qū)。 散列分區(qū)為通過(guò)指定分區(qū)編號(hào)來(lái)均勻分布數(shù)據(jù)的一種分區(qū)類型,因?yàn)橥ㄟ^(guò)在I/O設(shè)備上進(jìn)行散列分區(qū),使得這些分區(qū)大小一致。 例一:CREATE TABLE HASH_TABLE ( COL NUMBER(8), INF VARCHAR2(100) ) PARTITION BY HASH (COL) ( PARTITION PART01 TABLESPACE HASH_TS01, PARTITION PART02 TABLESPACE HASH_TS02, PARTITION PART03 TABLESPACE HASH_TS03 ) 簡(jiǎn)寫:CREATE TABLE emp ( empno NUMBER (4), ename VARCHAR2 (30), sal NUMBER ) PARTITION BY HASH (empno) PARTITIONS 8 STORE IN (emp1,emp2,emp3,emp4,emp5,emp6,emp7,emp8); hash分區(qū)最主要的機(jī)制是根據(jù)hash算法來(lái)計(jì)算具體某條紀(jì)錄應(yīng)該插入到哪個(gè)分區(qū)中,hash算法中最重要的是hash函數(shù),Oracle中如果你要使用hash分區(qū),只需指定分區(qū)的數(shù)量即可。建議分區(qū)的數(shù)量采用2的n次方,這樣可以使得各個(gè)分區(qū)間數(shù)據(jù)分布更加均勻。組合范圍散列分區(qū) 這種分區(qū)是基于范圍分區(qū)和列表分區(qū),表首先按某列進(jìn)行范圍分區(qū),然后再按某列進(jìn)行列表分區(qū),分區(qū)之中的分區(qū)被稱為子分區(qū)。CREATE TABLE SALES ( PRODUCT_ID VARCHAR2(5), SALES_DATE DATE, SALES_COST NUMBER(10), STATUS VARCHAR2(20) ) PARTITION BY RANGE(SALES_DATE) SUBPARTITION BY LIST (STATUS) ( PARTITION P1 VALUES LESS THAN(TO_DATE('2003-01-01','YYYY-MM-DD'))TABLESPACE rptfact2009 ( SUBPARTITION P1SUB1 VALUES ('ACTIVE') TABLESPACE rptfact2009, SUBPARTITION P1SUB2 VALUES ('INACTIVE') TABLESPACE rptfact2009 ), PARTITION P2 VALUES LESS THAN (TO_DATE('2003-03-01','YYYY-MM-DD')) TABLESPACE rptfact2009 ( SUBPARTITION P2SUB1 VALUES ('ACTIVE') TABLESPACE rptfact2009, SUBPARTITION P2SUB2 VALUES ('INACTIVE') TABLESPACE rptfact2009 ) ) 復(fù)合范圍散列分區(qū): 這種分區(qū)是基于范圍分區(qū)和散列分區(qū),表首先按某列進(jìn)行范圍分區(qū),然后再按某列進(jìn)行散列分區(qū)。create table dinya_test ( transaction_id number primary key, item_id number(8) not null, item_description varchar2(300), transaction_date date ) partition by range(transaction_date)subpartition by hash(transaction_id) subpartitions 3 store in (dinya_space01,dinya_space02,dinya_space03) ( partition part_01 values less than(to_date(‘2006-01-01','yyyy-mm-dd')), partition part_02 values less than(to_date(‘2010-01-01','yyyy-mm-dd')), partition part_03 values less than(maxvalue) ); 有關(guān)表分區(qū)的一些維護(hù)性操作: 添加分區(qū) 以下代碼給SALES表添加了一個(gè)P3分區(qū)ALTER TABLE SALES ADD PARTITION P3 VALUES LESS THAN(TO_DATE('2003-06-01','YYYY-MM-DD')); 注意:以上添加的分區(qū)界限應(yīng)該高于最后一個(gè)分區(qū)界限。以下代碼給SALES表的P3分區(qū)添加了一個(gè)P3SUB1子分區(qū)ALTER TABLE SALES MODIFY PARTITION P3 ADD SUBPARTITION P3SUB1 VALUES('COMPLETE'); 刪除分區(qū) 以下代碼刪除了P3表分區(qū):ALTER TABLE SALES DROP PARTITION P3; 在以下代碼刪除了P4SUB1子分區(qū):ALTER TABLE SALES DROP SUBPARTITION P4SUB1; 注意:如果刪除的分區(qū)是表中唯一的分區(qū),那么此分區(qū)將不能被刪除,要想刪除此分區(qū),必須刪除表。截?cái)喾謪^(qū) 截?cái)嗄硞€(gè)分區(qū)是指刪除某個(gè)分區(qū)中的數(shù)據(jù),并不會(huì)刪除分區(qū),也不會(huì)刪除其它分區(qū)中的數(shù)據(jù)。當(dāng)表中即使只有一個(gè)分區(qū)時(shí),也可以截?cái)嘣摲謪^(qū)。通過(guò)以下代碼截?cái)喾謪^(qū):ALTER TABLE SALES TRUNCATE PARTITION P2; 通過(guò)以下代碼截?cái)嘧臃謪^(qū):ALTER TABLE SALES TRUNCATE SUBPARTITION P2SUB2; 合并分區(qū) 合并分區(qū)是將相鄰的分區(qū)合并成一個(gè)分區(qū),結(jié)果分區(qū)將采用較高分區(qū)的界限,值得注意的是,不能將分區(qū)合并到界限較低的分區(qū)。以下代碼實(shí)現(xiàn)了P1 P2分區(qū)的合并:ALTER TABLE SALES MERGE PARTITIONS P1,P2 INTO PARTITION P2; 拆分分區(qū) 拆分分區(qū)將一個(gè)分區(qū)拆分兩個(gè)新分區(qū),拆分后原來(lái)分區(qū)不再存在。注意不能對(duì)HASH類型的分區(qū)進(jìn)行拆分。ALTER TABLE SALES SBLIT PARTITION P2 AT(TO_DATE('2003-02-01','YYYY-MM-DD')) INTO (PARTITION P21,PARTITION P22); 接合分區(qū)(coalesca) 結(jié)合分區(qū)是將散列分區(qū)中的數(shù)據(jù)接合到其它分區(qū)中,當(dāng)散列分區(qū)中的數(shù)據(jù)比較大時(shí),可以增加散列分區(qū),然后進(jìn)行接合,值得注意的是,接合分區(qū)只能用于散列分區(qū)中。通過(guò)以下代碼進(jìn)行接合分區(qū):ALTER TABLE SALES COALESCA PARTITION; 重命名表分區(qū) 以下代碼將P21更改為P2ALTER TABLE SALES RENAME PARTITION P21 TO P2; 相關(guān)查詢 -- 跨分區(qū)查詢 select sum( ) from (select count() cn from t_table_SS PARTITION (P200709_1) union all select count(*) cn from t_table_SS PARTITION (P200709_2) );--查詢表上有多少分區(qū) SELECT * FROM useR_TAB_PARTITIONS WHERE TABLE_NAME='tableName'--查詢索引信息 select object_name,object_type,tablespace_name,sum(value) from v$segment_statistics where statistic_name IN ('physical reads','physical write','logical reads')and object_type='INDEX' group by object_name,object_type,tablespace_name order by 4 desc--顯示數(shù)據(jù)庫(kù)所有分區(qū)表的信息: select * from DBA_PART_TABLES--顯示當(dāng)前用戶可訪問(wèn)的所有分區(qū)表信息: select * from ALL_PART_TABLES--顯示當(dāng)前用戶所有分區(qū)表的信息: select * from USER_PART_TABLES--顯示表分區(qū)信息 顯示數(shù)據(jù)庫(kù)所有分區(qū)表的詳細(xì)分區(qū)信息: select * from DBA_TAB_PARTITIONS--顯示當(dāng)前用戶可訪問(wèn)的所有分區(qū)表的詳細(xì)分區(qū)信息: select * from ALL_TAB_PARTITIONS--顯示當(dāng)前用戶所有分區(qū)表的詳細(xì)分區(qū)信息: select * from USER_TAB_PARTITIONS--顯示子分區(qū)信息 顯示數(shù)據(jù)庫(kù)所有組合分區(qū)表的子分區(qū)信息: select * from DBA_TAB_SUBPARTITIONS--顯示當(dāng)前用戶可訪問(wèn)的所有組合分區(qū)表的子分區(qū)信息: select * from ALL_TAB_SUBPARTITIONS--顯示當(dāng)前用戶所有組合分區(qū)表的子分區(qū)信息: select * from USER_TAB_SUBPARTITIONS--顯示分區(qū)列 顯示數(shù)據(jù)庫(kù)所有分區(qū)表的分區(qū)列信息: select * from DBA_PART_KEY_COLUMNS--顯示當(dāng)前用戶可訪問(wèn)的所有分區(qū)表的分區(qū)列信息: select * from ALL_PART_KEY_COLUMNS--顯示當(dāng)前用戶所有分區(qū)表的分區(qū)列信息: select * from USER_PART_KEY_COLUMNS--顯示子分區(qū)列 顯示數(shù)據(jù)庫(kù)所有分區(qū)表的子分區(qū)列信息: select * from DBA_SUBPART_KEY_COLUMNS--顯示當(dāng)前用戶可訪問(wèn)的所有分區(qū)表的子分區(qū)列信息: select * from ALL_SUBPART_KEY_COLUMNS--顯示當(dāng)前用戶所有分區(qū)表的子分區(qū)列信息: select * from USER_SUBPART_KEY_COLUMNS--怎樣查詢出oracle數(shù)據(jù)庫(kù)中所有的的分區(qū)表 select * from user_tables a where a.partitioned='YES'--刪除一個(gè)表的數(shù)據(jù)是 truncate table table_name;--刪除分區(qū)表一個(gè)分區(qū)的數(shù)據(jù)是 alter table table_name truncate partition p5; --------------------------------------------------------------------------------------

?

總結(jié)

以上是生活随笔為你收集整理的数据库表设计、 数据库分层、myslq水平拆分、oracle表分区的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。