【原创】一个亿级数据库优化过程
第一部分 棉花數(shù)據(jù)庫(kù)問(wèn)題和分析
1.問(wèn)題sql
數(shù)據(jù)庫(kù)的版本是9i,問(wèn)題sql有兩個(gè):
Sql1:
| SELECT ?c_lotno ???????? FROM b_ctn_normal ?WHERE d_prodatetime BETWEEN to_date('2011-07-01', 'yyyy-mm-dd HH24:MI:SS') AND ??????????????????????????? ?to_date('2012-07-03', 'yyyy-mm-dd HH24:MI:SS') ??????????????????????????? ?AND n_madein = 65 ??????????????????????????? ?AND rownum < 31 |
Sql2:
| SELECT count(c_bale) ???????? FROM b_ctn_normal ?WHERE d_prodatetime BETWEEN to_date('2011-07-01', 'yyyy-mm-dd HH24:MI:SS') AND ??????????????????????????? ?to_date('2012-07-03', 'yyyy-mm-dd HH24:MI:SS') |
?
這倆sql其實(shí)非常簡(jiǎn)單,就是一個(gè)按照時(shí)間的分頁(yè)查詢(xún),一個(gè)查詢(xún)時(shí)間范圍內(nèi)的總數(shù)據(jù)量。
但是這個(gè)表的數(shù)據(jù)量很大,41803656條數(shù)據(jù),單表容量超過(guò)21G。因此查詢(xún)非常慢,僅僅查詢(xún)30條數(shù)據(jù)就需要耗費(fèi)十幾分鐘。甚至查不出結(jié)果。
?
2 表概況
表b_ctn_normal是一個(gè)分區(qū)表,按照D_VERIFYDATETIME進(jìn)行了range分區(qū),分區(qū)的策略為2010年前每年一個(gè)分區(qū),2010年后每月一個(gè)分區(qū).該表的數(shù)據(jù)量為41803656條。
| partition by range (D_VERIFYDATETIME) partition PART_20080101 values less than (TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) ? partition PART_20090101 values less than (TO_DATE(' 2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))—后續(xù)的省略 ? |
另外該表上建了大量的索引,見(jiàn)表1:
3.表存在的問(wèn)題
以下是索引的概況統(tǒng)計(jì)信息。
?
| NDEX_NAME | DISTINCT_KEYS | NUM_ROWS | SAMPLE_SIZE |
| I_CTN_NORMAL_99 | 4 | 41805079.0630631 | 8459008 |
| I_NORMAL_MADEIN1 | 17 | 41804897.3546108 | 9544621 |
| I_CTN_NORMAL_66 | 80 | 41767143.7096454 | 9580744 |
| I_CTN_NORMAL_77 | 86 | 41473125.0963043 | 9479665 |
| I_CTN_NORMAL_22 | 366 | 41875654.4438373 | 9937607 |
| I_CTN_NORMAL_11 | 889 | 41867424.9314059 | 11007070 |
| I_CTN_NORMAL_55 | 1957 | 40169648.695544 | 9058949 |
| I_NORMAL_UPLOADTIME1 | 17253 | 41866396.7193889 | 10087608 |
| I_CTN_NORMAL_33 | 384472 | 41842227.8696896 | 10621842 |
| I_NORMAL_D_COLORGRADETIME | 1485863 | 41727490.2734861 | 9119757 |
| GLOBAL_INDEX_D_VERIFYDATETIME | 21162573 | 41804256 | 9592128 |
| PRIMARY1_ID | 41804473 | 41804473 | 9540784 |
| UNI_NORMAL_C_BALE1 | 41841809 | 41841809.1781587 | 7023237 |
【表1】索引概況
?
l? 表不是很寬,但是竟然建了13個(gè)索引,而且8個(gè)索引可選性很差,每個(gè)索引都占據(jù)不少段空間,極大的浪費(fèi)了存儲(chǔ)空間。
l? 索引沒(méi)有分區(qū),千萬(wàn)級(jí)別的數(shù)據(jù)量,本身查找索引就很耗時(shí),因此應(yīng)當(dāng)對(duì)索引分區(qū)其高索引檢索性能。
l? 表的索引和表應(yīng)該建立在不同的表空間分開(kāi)存放,同時(shí)表的分區(qū)在不同的表空間存放。
l? 分區(qū)的記錄不均勻,分區(qū)不合理
分區(qū)的統(tǒng)計(jì)信息顯示,大量的數(shù)據(jù)集中在了PART_20100101和PART_20090101分區(qū),分區(qū)很不合理,大大削弱了分區(qū)表的作用。應(yīng)該對(duì)分區(qū)進(jìn)行細(xì)粒度的劃分,均勻分布數(shù)據(jù)。
| TABLE_NAME | PARTITION_NAME | NUM_ROWS | SAMPLE_SIZE |
| B_CTN_NORMAL | PART_20100101 | 15580400 | 2883811 |
| B_CTN_NORMAL | PART_20090101 | 13007483 | 2420607 |
| B_CTN_NORMAL | PART_20101201 | 3809673 | 709735 |
| B_CTN_NORMAL | PART_20110101 | 2656138 | 494675 |
| B_CTN_NORMAL | PART_20101101 | 2641196 | 492471 |
| B_CTN_NORMAL | PART_20110201 | 1169697 | 217919 |
| B_CTN_NORMAL | PART_20100201 | 1106187 | 205854 |
| B_CTN_NORMAL | PART_20110401 | 662618 | 123426 |
| B_CTN_NORMAL | PART_20110301 | 271190 | 50600 |
| B_CTN_NORMAL | PART_20100501 | 205173 | 37933 |
| B_CTN_NORMAL | PART_20100401 | 194223 | 35804 |
| B_CTN_NORMAL | PART_20100601 | 154195 | 28641 |
| B_CTN_NORMAL | PART_20110501 | 137085 | 25587 |
| B_CTN_NORMAL | PART_20100301 | 105747 | 19575 |
| B_CTN_NORMAL | PART_20101001 | 64424 | 11960 |
| B_CTN_NORMAL | PART_20100701 | 33743 | 6206 |
| B_CTN_NORMAL | PART_20100801 | 4044 | 725 |
| B_CTN_NORMAL | PART_20100901 | 283 | 283 |
| B_CTN_NORMAL | PART_20111001 | 80 | 80 |
| B_CTN_NORMAL | PART_20080101 | 53 | 53 |
| B_CTN_NORMAL | PART_20111201 | 21 | 21 |
| B_CTN_NORMAL | PART_20120601 | 2 | 2 |
| B_CTN_NORMAL | PART_20120301 | 1 | 1 |
| B_CTN_NORMAL | PART_20110601 | 0 |
|
| B_CTN_NORMAL | PART_20110701 | 0 |
|
| B_CTN_NORMAL | PART_20120401 | 0 |
|
| B_CTN_NORMAL | PART_20120801 | 0 |
|
| B_CTN_NORMAL | PART_20120701 | 0 |
|
| B_CTN_NORMAL | PART_20120501 | 0 |
|
| B_CTN_NORMAL | PART_20120201 | 0 |
|
| B_CTN_NORMAL | PART_20120101 | 0 |
|
| B_CTN_NORMAL | PART_20111101 | 0 |
|
| B_CTN_NORMAL | PART_20110801 | 0 |
|
| B_CTN_NORMAL | PART_20110901 | 0 |
|
?
注:以上的統(tǒng)計(jì)信息都是最新收集的.
4.分析制定策略
結(jié)合問(wèn)題sql發(fā)現(xiàn), 兩個(gè)查詢(xún)共同依賴(lài)于d_prodatetime字段的過(guò)濾,但是該字段重復(fù)值很多,根據(jù)統(tǒng)計(jì)信息,該列的NUM_DISTINCT為456,因此只依靠索引沒(méi)有意義,CBO不會(huì)選擇索引而是全表掃描。執(zhí)行這兩個(gè)查詢(xún)的時(shí)候?qū)?shù)據(jù)沒(méi)有區(qū)分度,選擇了4K萬(wàn)數(shù)據(jù)進(jìn)行全表掃描,效率可寫(xiě)而至。
而該查詢(xún)較為簡(jiǎn)單,經(jīng)過(guò)仔細(xì)的分析并研究目前的分區(qū)策略,我認(rèn)為最佳的策略是增加范圍分區(qū)字段,將表重新分區(qū),分區(qū)條件納入d_prodatetime字段。這樣查詢(xún)時(shí)可以以d_prodatetime進(jìn)行分區(qū)裁減從而減少掃描的數(shù)據(jù)量。需要分析字段的值的分布區(qū)間,平均分配到各分區(qū)。經(jīng)過(guò)分析表的數(shù)據(jù)分布,從節(jié)省時(shí)間上考慮,就以每?jī)蓚€(gè)月為一個(gè)范圍進(jìn)行分區(qū)。
| partition by range (D_VERIFYDATETIME, d_prodatetime) partition PART_20080101 values less than (TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'), TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) ? partition PART_20090101 values less than (TO_DATE(' 2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'), TO_DATE(' 2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) ? |
考慮到sql1中有對(duì)n_madein的過(guò)濾,分析該字段,字段值總共為17種,為number類(lèi)型,而且該字段值在字段D_VERIFYDATETIME, d_prodatetime表示的區(qū)間中分布很均勻,因此,在上述分區(qū)基礎(chǔ)上增加list分區(qū),使分區(qū)策略變?yōu)镽ang-list復(fù)合分區(qū):
| partition by range (D_VERIFYDATETIME, d_prodatetime) subpartition by list(N_MADEIN) partition PART_20080101 values less than (range1,range2) ( subpartition p31 values(64), ?subpartition p32 values(37), ?subpartition p33 values(48), ?subpartition p34 values(55), …………… ), ? partition PART_20090101 values less than (range3,range4) ( subpartition p31 values(64), ?subpartition p32 values(37), ?subpartition p33 values(48), ?subpartition p34 values(55), ………….. ), ) ? |
這樣,sql1在執(zhí)行時(shí),會(huì)首先根據(jù)d_prodatetime裁減掉部分?jǐn)?shù)據(jù),然后再根據(jù)N_MADEIN再次裁減掉一部分,這樣sql1的性能應(yīng)該會(huì)得到很大提升。而對(duì)于僅僅含有N_MAADIN的過(guò)濾條件的查詢(xún),都會(huì)進(jìn)行分區(qū)裁減,減少數(shù)據(jù)量。具體性能提高多少,需要測(cè)試。
同時(shí),之前的分區(qū)字段D_VERIFYDATETIME的粒度應(yīng)該適當(dāng)?shù)臏p小。因?yàn)閐_prodatetime的重復(fù)值較多,以之前的分區(qū)粒度,2010年前的是每年一個(gè)分區(qū),這樣會(huì)導(dǎo)致d_prodatetime分區(qū)后數(shù)據(jù)會(huì)很不均勻,若查詢(xún)2010年之前的數(shù)據(jù),則d_prodatetime裁減的效果會(huì)不好,因此需要考慮d_prodatetime的字段值,重新規(guī)劃分區(qū)粒度。分區(qū)粒度的大小需要考慮到d_prodatetime的范圍分布情況。通過(guò)分析決定和d_prodatetime字段使用同樣的分區(qū)范圍。
?
由于需要對(duì)表重新分區(qū),因此需要重建表。如果在已有的分區(qū)策略下增加分區(qū),則直接alter表即可,oracle提供了豐富的方法為不同的分區(qū)增加新的分區(qū);但是修改分區(qū)策略,必須重建表。而表數(shù)據(jù)量巨大,單表超過(guò)20G,因此數(shù)據(jù)的加載成為頭疼的問(wèn)題,如果在生產(chǎn)環(huán)境,產(chǎn)生的日志也很巨大。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
第二部分 試驗(yàn)過(guò)程結(jié)果及分析
為了能試驗(yàn)本文預(yù)測(cè)的效果,于是我在我本機(jī)騰出了30G的空間,將庫(kù)置于非歸檔模式,然后用database link以insert append的方式直接加載數(shù)據(jù)。通過(guò)仔細(xì)的權(quán)衡,我創(chuàng)建的分區(qū)表如下(限于時(shí)間關(guān)系,將所有表分區(qū)和索引分區(qū)建在一個(gè)表空間內(nèi)):
--ddl過(guò)長(zhǎng),省略(見(jiàn)附件)
(注:復(fù)合分區(qū)可以為二級(jí)分區(qū)創(chuàng)建一個(gè)template,從而減少建表DDL的篇幅)
考慮只有本文開(kāi)頭的兩個(gè)查詢(xún)問(wèn)題突出,因此我只建立了倆索引,選擇了全局范圍分區(qū)索引。
| --創(chuàng)建分區(qū)索引GLOBAL_INDEX_D_VERIFYDATETIME CREATE INDEX GLOBAL_INDEX_D_VERIFYDATETIME ON b_ctn_normal(D_VERIFYDATETIME) ?? GLOBAL PARTITION BY RANGE(D_VERIFYDATETIME)( partition part_index_0 values less than(to_date('2008-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_1 values less than(to_date('2008-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_2 values less than(to_date('2008-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_3 values less than(to_date('2008-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_4 values less than(to_date('2008-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_5 values less than(to_date('2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_6 values less than(to_date('2009-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_7 values less than(to_date('2009-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_8 values less than(to_date('2009-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_9 values less than(to_date('2009-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_10 values less than(to_date('2009-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_11 values less than(to_date('2010-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_12 values less than(to_date('2010-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_13 values less than(to_date('2010-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_14 values less than(to_date('2010-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_15 values less than(to_date('2010-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_16 values less than(to_date('2010-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_17 values less than(to_date('2011-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_18 values less than(to_date('2011-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_19 values less than(to_date('2011-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_20 values less than(to_date('2011-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_21 values less than(to_date('2011-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_22 values less than(to_date('2011-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_23 values less than(to_date('2012-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_24 values less than(to_date('2012-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_25 values less than(to_date('2012-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_26 values less than(to_date('2012-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_27 values less than(to_date('2012-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_28 values less than(to_date('2012-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index_29 values less than(maxvalue) ) |
注:分區(qū)索引也可以使用本地前綴索引,可以減少DDL篇幅
考慮到D_PRODATETIME的值較多,當(dāng)查詢(xún)來(lái)臨時(shí),oracle首先以查詢(xún)where條件中的D_PRODATETIME進(jìn)行裁減,到目標(biāo)分區(qū)之后,如果有索引的話(huà),應(yīng)該可以進(jìn)行INDEX RANGE SCAN進(jìn)行掃描,因此先建立分區(qū)索引試試。同樣選擇了全局范圍分區(qū)索引。
| --創(chuàng)建分區(qū)索引GLOBAL_INDEX_D_PRODATETIME CREATE INDEX GLOBAL_INDEX_D_PRODATETIME ON b_ctn_normal(D_PRODATETIME) ?? GLOBAL PARTITION BY RANGE(D_PRODATETIME)( partition part_index1_0 values less than(to_date('2008-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_1 values less than(to_date('2008-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_2 values less than(to_date('2008-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_3 values less than(to_date('2008-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_4 values less than(to_date('2008-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_5 values less than(to_date('2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_6 values less than(to_date('2009-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_7 values less than(to_date('2009-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_8 values less than(to_date('2009-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_9 values less than(to_date('2009-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_10 values less than(to_date('2009-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_11 values less than(to_date('2010-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_12 values less than(to_date('2010-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_13 values less than(to_date('2010-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_14 values less than(to_date('2010-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_15 values less than(to_date('2010-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_16 values less than(to_date('2010-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_17 values less than(to_date('2011-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_18 values less than(to_date('2011-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_19 values less than(to_date('2011-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_20 values less than(to_date('2011-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_21 values less than(to_date('2011-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_22 values less than(to_date('2011-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_23 values less than(to_date('2012-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_24 values less than(to_date('2012-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_25 values less than(to_date('2012-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_26 values less than(to_date('2012-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_27 values less than(to_date('2012-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_28 values less than(to_date('2012-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')), partition part_index1_29 values less than(maxvalue) )) |
下面是加載數(shù)據(jù)以及實(shí)施步驟:
l? 表數(shù)據(jù)加載
創(chuàng)建db link “ctn”.
Insert /*+append*/ into b_ctn_normal select * from b_ctn_normal@ctn;
加載速度還可以,大概30分鐘加載完,加載數(shù)據(jù)量4400W。
l? 分別按照上述的策略創(chuàng)建分區(qū)索引
GLOBAL_INDEX_D_VERIFYDATETIME和GLOBAL_INDEX_D_PRODATETIME
索引創(chuàng)建約為30分鐘
l? 執(zhí)行sql1和sql2和原始庫(kù)進(jìn)行對(duì)比
?
Sql1的測(cè)試結(jié)果對(duì)比:
| ? | 返回行數(shù) | Pl/sql查詢(xún) | Sqlplus跟蹤 |
| 優(yōu)化前 | 30 | >15分鐘 | 00: 04: 31.62 |
| 優(yōu)化后 | 30 | <0.4秒 | 00: 00: 00.03 |
?
Sql2的測(cè)試結(jié)果對(duì)比:
| ? | 返回行數(shù) | Pl/sql查詢(xún) | Sqlplus跟蹤 |
| 優(yōu)化前 | 5529 | ? | 00: 05: 42.67 |
| 優(yōu)化后 | 5529 | <0.02秒 | 00: 00: 00.01 |
?
通過(guò)以上對(duì)比結(jié)果,顯示新的分區(qū)策略帶來(lái)了巨大的性能提升,顯示了oracle分區(qū)技術(shù)的強(qiáng)大威力。原來(lái)十幾分鐘甚至返回不了結(jié)果的查詢(xún)現(xiàn)在毫秒就返回?cái)?shù)據(jù)。
下面分析優(yōu)化后的執(zhí)行計(jì)劃:
?
Sql1執(zhí)行計(jì)劃:
?
通過(guò)執(zhí)行計(jì)劃可以看出,查詢(xún)正確的使用了d_prodatetime字段進(jìn)行了分區(qū)裁減,然后使用到了該列的分區(qū)索引,但是并沒(méi)有使用n_madein進(jìn)行裁減。于是改變了下查詢(xún)條件,將查詢(xún)的數(shù)據(jù)量增大:
| SELECT ?c_lotno ???????? FROM b_ctn_normal ?WHERE d_prodatetime BETWEEN to_date('2011-07-01', 'yyyy-mm-dd HH24:MI:SS') AND ??????????????????????????? ?to_date('2012-07-03', 'yyyy-mm-dd HH24:MI:SS') ??????????????????????????? ?AND n_madein = 65 ??????????????????????????? ?AND rownum < 5000 |
?
這次,查詢(xún)使用了二級(jí)分區(qū)裁減。先是對(duì)一級(jí)分區(qū)進(jìn)行裁減,然后又對(duì)二級(jí)分區(qū)進(jìn)行裁減,最后對(duì)二級(jí)分區(qū)使用N_MADEIN進(jìn)行全表掃描。執(zhí)行計(jì)劃顯示,查詢(xún)5000條數(shù)據(jù)時(shí)耗時(shí)增加了很多,因?yàn)閽呙璧臄?shù)據(jù)量實(shí)在太大了,查詢(xún)需要掃描很多分區(qū)。這樣只能通過(guò)減少一次查詢(xún)的數(shù)據(jù)量來(lái)保證性能。通過(guò)和開(kāi)發(fā)人員確認(rèn),一次查詢(xún)一般不用返回這么多數(shù)據(jù)。
?
Sql2執(zhí)行計(jì)劃:
?
執(zhí)行計(jì)劃已經(jīng)顯示的很明確,一級(jí)分區(qū)按照新分區(qū)的字段進(jìn)行裁減,然后使用建立的分區(qū)索引,性能很高。
?????????? 雖然新的分區(qū)策略顯示了巨大的性能提升,有效的解決了性能問(wèn)題,但是仔細(xì)分析一下,仍然存在一些問(wèn)題:
u? 分區(qū)較多,在4K萬(wàn)級(jí)別的表上,分區(qū)多達(dá)493個(gè),這有些過(guò)分了。需要減少分區(qū)數(shù)量。目前的分區(qū)是每倆月一個(gè)分區(qū),目前的數(shù)據(jù)分布比重新分區(qū)前均勻了很多,但是仍然存在不均勻現(xiàn)象,而且每倆月一個(gè)分區(qū)仍然較多。因此需要維持現(xiàn)在的范圍分區(qū)字段不變,將現(xiàn)在的倆月一個(gè)分區(qū)的條件變化一下,分析數(shù)據(jù)的分布區(qū)間,制定一個(gè)不均勻的分區(qū)條件。如2010年8月的數(shù)據(jù)很多,那可以分別以2010-08-01~2010-08-15~2010-08-30為區(qū)間劃分。如果2010年9-12月數(shù)據(jù)很少,那么可以將9-12月合并為一個(gè)分區(qū)。盡可能的均勻劃分分區(qū)記錄數(shù),也減少分區(qū)數(shù)量。
u? 評(píng)估二級(jí)分區(qū)的必要性。總的分區(qū)數(shù)是1級(jí)分區(qū)和二級(jí)分區(qū)的乘積,為M*N的關(guān)系。二級(jí)分區(qū)的增加,大大增加了分區(qū)數(shù)。分析發(fā)現(xiàn),有接近一半的二級(jí)分區(qū)是空閑的,并沒(méi)有記錄裝入,浪費(fèi)了大量的空間。而且目前的sql并沒(méi)有使用到二級(jí)分區(qū)裁減,因此需要評(píng)估二級(jí)分區(qū)帶來(lái)的性能提高。然后考慮是否將二級(jí)分區(qū)去掉只采用范圍分區(qū)。去掉二級(jí)分區(qū),目前對(duì)性能是沒(méi)有壞處的,而且未來(lái)如果用到對(duì)N_MADEIN字段的裁剪,直接alter表即可增加二級(jí)分區(qū),不用重建。因此建議去掉。
l? 總結(jié)
分區(qū)是處理大表的首要應(yīng)對(duì)策略,但是分區(qū)字段的選取和分區(qū)的方法需要仔細(xì)權(quán)衡,一般第一想到的分區(qū)字段都是合理的,但是一些隱含的字段沒(méi)有考慮到,未來(lái)數(shù)據(jù)量上去了,這些隱含的條件造成的性能問(wèn)題就暴露出來(lái)了,因此還是需要全面的分析。
對(duì)表進(jìn)行了分區(qū),相應(yīng)的也要對(duì)索引進(jìn)行分區(qū),這樣可以裁減掉部分索引,然后裁減掉記錄,雖然是海量數(shù)據(jù),但是卻擁有極高的查詢(xún)速度。記得在一本書(shū)上看過(guò),作者說(shuō),正是因?yàn)橛辛朔謪^(qū)技術(shù),oracle才敢號(hào)稱(chēng)是海量數(shù)據(jù)庫(kù)。
?
Reference:
【http://docs.oracle.com/cd/B19306_01/server.102/b14231/partiti.htm#i1009216】
轉(zhuǎn)載于:https://www.cnblogs.com/zhangxsh/p/3494420.html
總結(jié)
以上是生活随笔為你收集整理的【原创】一个亿级数据库优化过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 车载大屏沾满指纹怎么办,通用汽车申请自清
- 下一篇: 韩顺平 Mysql数据库优化(一) 优化