SQLデータベースパーティションテーブルと読み取りと書き込みの分離

データベースの構造を最適化するには多くの方法があり、主に2つのタイプがあります。

   1つは、ストアドプロシージャを使用して、一般的に使用されるSQLクエリステートメントを置き換え、SQLステートメントの解析とコンパイルのプロセスを削減することです。

     もう1つは、データベース管理システムでパーティションテーブル方式を使用することです。ストアドプロシージャを使用した最適化方法には、実行速度が速いという利点がありますが、デバッグには役立ちません。また、データベースキャッシュメカニズムを使用する方法もありません。したがって、システムのセキュリティとパフォーマンスの要件が高い場合は、パーティションテーブルを使用することをお勧めします。ただし、十分なデータがある限り、データベースパーティションテーブルを通じてクエリの効率を上げる必要はありませんが、データがセグメント化されているときにパーティションテーブルを使用する必要があるかどうかを検討するだけでよいことに注意してください。

パーティショニングの利点:

1)可用性の向上:テーブルのパーティションに障害が発生しても、他のパーティションのテーブルのデータは引き続き利用できます。

2)便利なメンテナンス:テーブルのパーティションに障害が発生した場合、データを修復する必要があります。修復できるのはパーティションのみです。

3)I / Oのバランス:異なるパーティションをディスクにマップしてI / Oのバランスを取り、システム全体のパフォーマンスを向上させることができます。

4)クエリのパフォーマンスの向上:パーティション化されたオブジェクトのクエリでは、気になるパーティションのみを検索して、検索速度を向上させることができます。

データベーステーブルを分割するには、水平テーブルパーティションと垂直テーブルパーティションの2つの方法があります。

 水平分割:目的は、テーブルを複数のテーブルに分割することです。各テーブルには同じ数の列(テーブルフィールド)が含まれますが、レコード(データ行)の数は減少します。たとえば、1億行のレコードを含むデータベーステーブルを、水平分割法に従って12の小さなテーブルに分割できます。各小さなテーブルは、今年の1月から12月までのデータを表します。このように、特定の月のデータをクエリする必要があるクエリは、対応する月のテーブルをクエリするだけでよく、大きなテーブルに格納されているすべての月のデータからのクエリを回避できます。SQLステートメントの実行効率によると、小さなテーブルからのクエリの効率は、大きなテーブルからのクエリの効率よりもはるかに高いことは間違いありません。

    垂直分割:この方法は、水平分割とは逆の方法であり、垂直方向から分割すると、元のテーブルが列数の少ない複数のテーブルに分割されます。日常のアプリケーションでは、水平分割は最も一般的に使用される分割方法と言えます。

1.パーティション テクノロジーの
    概要ORACLEパーティションは、非常に大きなテーブルやインデックスなど処理するテクノロジーです大きなテーブルとインデックスを分割ルールに従って管理できるいくつかの小さなブロックに分割することにより、各テーブルが大きな個別のオブジェクトとして管理され、大量のデータに対してスケーラブルなパフォーマンスを提供することが回避されます。パーティショニングは、より小さなストレージユニットに操作を割り当てることで管理操作に必要な時間を短縮し、強化された並列処理によってパフォーマンスを向上させ、障害が発生したデータのパーティションをシールドすることで可用性を高めます。
2.データベースパーティション設計の最適化計画
2.1パーティション分割する必要がある大きなテーブルを決定します。

    パーティション化テクノロジーを使用する場合、データベース内のすべてのテーブルがパーティション化されるわけではなく、大きなデータボリュームを持ついくつかの大きなテーブルに対してのみパーティション化されます。パーティショニングの定義によれば、パーティショニングは実際にルールに従って大きなデータセグメントをいくつかの小さなデータセグメントに分割することがわかり、テーブルオブジェクト自体が小さい場合、パーティション化の意味が失われます。経験によれば、パーティション化する必要があるのは、データ量が1,000万を超えるテーブルのみです。
SQL> select owner、table_name、num_rows
from dba_tables
where num_rows> 10000000
and partitioned = 'NO';
注:上記のステートメントを使用して、パーティション分割が必要な大きなテーブルをカウントする場合、最初にデータベースシステムの統計を収集する必要があります。そうしないと、num_rowsのデータが不正確になり、テーブルオブジェクトのレコード数を正しく表現できません。
2.2パーティションタイプとパーティションフィールドの選択について話し合う:
    このステップは非常に重要ですパーティションタイプとパーティションフィールドの選択は、データテーブルのアクセスパフォーマンスに深刻な影響を与えます。間違ったパーティションタイプまたはパーティションフィールドを選択すると、パーティションを作成しない場合よりもデータベースのパフォーマンスに大きな悪影響を与えるため、パーティションタイプとパーティションフィールドを決定する際はプロジェクトチームと話し合い、ビジネスニーズとビジネスロジックに従ってそれをまとめてください。
経験によれば、パーティションタイプを選択する手順は
次のとおりです。1)最初に、テーブルのどのフィールドがselectステートメントの述語で最も頻繁に使用されるかを決定します。このフィールドはパーティションフィールドとして使用されます。
    パーティション分割の目的は、ルールに従って大きなテーブルのデータセグメントをいくつかの小さなデータセグメントに分離することであり、インデックスもいくつかの小さなインデックスセグメントに分離されます。データアクセス中、インデックスに従ってアクセスする必要があるのは、小さなインデックスセグメントの1つだけです。データセグメントの1つ。これにより、アクセスする必要があるデータの量を減らし、最適化の目的を達成します。selectステートメントの述語にパーティションフィールドが含まれていない場合は、インデックスセグメント全体にアクセスし、最後にすべての小さなデータセグメントにアクセスして、アクセスする必要のあるデータを見つける必要があります。
2)パーティションフィールドの特性に応じて、パーティションタイプを決定します。
    フィールドに明確な順序がある場合、テーブルは範囲分割に適しています。例:時間、フィールドに明確な範囲順序関係がない場合、一意の値またはいくつかの値がある場合、テーブルはリストのパーティション化に適しています。例:部署、支店、このフィールドに明確な範囲の順序関係も特定の値もないがシリアル番号がある場合、テーブルはハッシュパーティションに適しています。など:バッチ番号、シリアル番号。
2.3データテーブルスペースとインデックステーブルスペース
    テーブルオブジェクトとインデックスオブジェクトを設計するための最初のルールは、テーブルとインデックスを分離することです。テーブルと対応するインデックスは、異なるテーブルスペース、できれば異なるディスクに設定されます。これにより、データ管理およびクエリ中に発生する多くのI / O競合を回避できます。

    この最適化スキームでは、パーティションごとに対応するテーブルスペースを作成し、テーブルパーティションを異なるテーブルスペースに格納して、異なるパーティション間のデータアクセスの分離を実現します。同時に、インデックスパーティションごとに独立したインデックスパーティションテーブルスペースも作成されます。

3.パーティションの種類

1.範囲パーティションの詳細な説明

範囲分割とは、データテーブルの値の範囲を分割し、値の範囲に基づいてデータを格納するパーティションを決定することです。シリアル番号によるパーティション化、時間によるパーティション化など。たとえば、シリアル番号によれば、part01には2000000未満、part02には2000000〜4000000が配置されます。

create table AAA
(
 id number primary key,
 indate date not null
)
partition by range(indate)
(
 partition part_01 values less than(to_date('2006-01-01','yyyy-mm-dd'))tablespace space01,
 partition part_02 values less than(to_date('2010-01-01','yyyy-mm-dd'))tablespace space02,
 partition part_03 values less than(maxvalue)tablespace space03
);

space01\ space02\ space03为建立的三个表空间,相当于把建立的一个大的表分在了3个不同的表空间的分区上了。

 

二、Hash分区(散列分区)详细说明

   散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在I/O设备上进行散列分区,使得这些分区大小一致。也就是只命名分区名称,这样均匀进行数据分布。

 

三、复合分区详细说明

   有时候我们需要根据范围分区后,每个分区内的数据再散列地分布在几个表空间中,这样我们就要使用复合分区。复合分区是先使用范围分区,然后在每个分区内再使用散列分区的一种分区方法。

partition by range(indate)subpartition by hash(id) 
subpartitions 3 store in (space01, space02, 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) 
 );

 

四、分区表操作

1、插入记录:insert into AAA values(1 ,sysdate);

2、查询分区表记录:select * from AAA partition(part_01);

3、更新分区表的记录:update AAA partition(part_01) t set indate=’’where id=1; 但是当更新的时候指定了分区,而根据查询的记录不在该分区中时,将不会更新数据

4、删除分区表记录:delete from AAA partition(part_02) t where id=4; 如果指定了分区,而条件中的数据又不在该分区中时,将不会删除任何数据。

5、增加一个分区:alter table AAA add partition part_04 values less than(to_date(’2012-01-01’,’yyyy-mm-dd’)) tablespace dinya_spa ce03; 增加一个分区的时候,增加的分区的条件必须大于现有分区的最大值,否则系统将提示ORA-14074 partition bound must collate higher than that of the last partition 错误。

6、合并一个分区:alter table AAA merge partitions part_01,part_02 into partition part_02; ,如果在合并的时候把合并后的分区定为part_01的时候,系统将提示ORA-14275 cannot reuse lower-bound partition as resulting partition 错误。

7、删除分区:alter table AAA drop partition part_01; 删除分区表的一个分区后,查询该表的数据时显示,该分区中的数据已全部丢失,所以执行删除分区动作时要慎重,确保先备份数据后再执行,或将分区合并。

 

五、建立索引

    分区表和一般表一样可以建立索引,分区表可以创建局部索引和全局索引。当分区中出现许多事务并且要保证所有分区中的数据记录的唯一性时采用全局索引。

1.       局部索引分区的建立:create index idx_t on AAA(id) 
 local 

partition idx_1 tablespace space01, 
partition idx_2 tablespace space02, 
partition idx_3 tablespace space03 
);

2.       全局索引建立时global 子句允许指定索引的范围值,这个范围值为索引字段的范围值:create index idx_t on AAA(id)
global partition by range(id) 

partition idx_1 values less than (1000) tablespace space01, 
partition idx_2 values less than (10000) tablespace space02, 
partition idx_3 values less than (maxvalue) tablespace space03 
);

当然也可以不指定索引分区名直接对整个表建立索引:

create index idx_t on AAA(id);

数据库的垂直切分和水平切分

数据切分可以是物理上的,对数据通过一系列的切分规则将数据分布到不同的DB服务器上,通过路由规则路由访问特定的数据库,这样一来每次访问面对的就不是单台服务器了,而是N台服务器,这样就可以降低单台机器的负载压力。

据切分也可以是数据库内的,对数据通过一系列的切分规则,将数据分布到一个数据库的不同表中,比如将article分为article_001,article_002等子表,若干个子表水平拼合有组成了逻辑上一个完整的article表,这样做的目的其实也是很简单的。 举个例子说明,比如article表中现在有5000w条数据,此时我们需要在这个表中增加(insert)一条新的数据,insert完毕后,数据库会针对这张表重新建立索引,5000w行数据建立索引的系统开销还是不容忽视的。但是反过来,假如我们将这个表分成100 个table呢,从article_001一直到article_100,5000w行数据平均下来,每个子表里边就只有50万行数据,这时候我们向一张只有50w行数据的table中insert数据后建立索引的时间就会呈数量级的下降,极大了提高了DB的运行时效率,提高了DB的并发量。当然分表的好处还不知这些,还有诸如写操作的锁操作等,都会带来很多显然的好处。

综上,分库降低了单点机器的负载;分表,提高了数据操作的效率,尤其是Write操作的效率

数据库的读写分离

 读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

       为什么要分库、分表、读写分?

       单表的数据量限制,当单表数据量到一定条数之后数据库性能会显著下降。数据多了之后,对数据库的读、写就会很多。分库减少单台数据库的压力。接触过几个分库分表的系统,都是通过主键进行散列分裤分表的。这类数据比较特殊,主键就是唯一的获取该条信息的主要途径。比如:京东的订单、财付通的交易记录等。。。该类数据的用法,就是通过订单号、交易号来查询该笔订单、交易。

        还有一类数据,比如用户信息,每个用户都有系统内部的一个userid,与userid对应的还有用户看到的登录名。那么如果分库分表的时候单纯通过userid进行散列分库,那么根据登录名来获取用户的信息,就无法知道该用户处于哪个数据库中。

       或许有朋友会说,我们可以维护一个email----userid的映射关系,根据email先查询到userid,在根据userid的分库分表规则到对应库的对应表来获取用户的记录信息。这么做是可以的,但是这个映射关系的条数本身也是个瓶颈,原则上是没有减少单表内数据的条数,算是一个单点。并且要维护这个映射关系和用户信息的一致性(修改登录名、多登录名等其他特殊需求),最大一个原因,其实用户信息是一个读大于写的库,web2.0都是以用户为中心,所有信息都和用户信息相关联,所以对用户信息拆分还是有一定局限性的。

       对于这类读大于写并且数据量增加不是很明显的数据库,推荐采用读写分离+缓存的模式,试想一下一个用户注册、修改用户信息、记录用户登录时间、记录用户登录IP、修改登录密码,这些是写操作。但是以上这些操作次数都是很小的,所以整个数据库的写压力是很小的。唯一一个比较大的就是记录用户登录时间、记录用户登录IP这类信息,只要把这些经常变动的信息排除在外,那么写操作可以忽略不计。所以读写分离首要解决的就是经常变化的数据的拆分,比如:用户登录时间、记录用户登录IP。这类信息可以单独独立出来,记录在持久化类的缓存中(可靠性要求并不高,登陆时间、IP丢了就丢了,下次来了就又来了)

        以oracle为例,主库负责写数据、读数据。读库仅负责读数据。每次有写库操作,同步更新cache,每次读取先读cache在读DB。写库就一个,读库可以有多个,采用dataguard来负责主库和多个读库的数据同步。

总结:
    Oracle数据库的分区技术可以改善查询性能,仅搜索自己关心的分区,提高检索速度。同时可以把不同的分区分离至不同的磁盘上,以平衡I/0
,改善整个系统的性能。除此之外,在数据维护方面,分区技术也有很大的优势。在进行历史数据转储时,只需要将需要转储的数据分区export备份出来转储至磁带中。而不需要将整张表全部export备份出来。在历史数据清理时可以将历史数据所在的分区truncate或drop,而不影响表的其他数据,同时释放空间。
发布了7 篇原创文章 · 获赞 69 · 访问量 20万+

おすすめ

転載: blog.csdn.net/u014320421/article/details/79484646