Slide 1

Slide 1 text

DBスペシャリスト午後2問1で覚える RDBMSの機能 (2) パーティショニング・パラレルクエリ・クラスタリング インフラ勉強会 2020/03/20 まつひさ(hmatsu47)

Slide 2

Slide 2 text

自己紹介 松久裕保(@hmatsu47) https://qiita.com/hmatsu47 名古屋でWebインフラのお守り係(非DBA) ○ 会社ではAmazon Aurora(MySQL 5.6互換版)を 使ってます MySQL 8.0:趣味・遊び ○ MySQL 8.0の薄い本を作って配っています https://qiita.com/hmatsu47/items/ceb75caf46e3c761095d ○ 現在8.0.19対応版です ○ GitHubリポジトリのほか、印刷版を勉強会などでタダで配っています 2

Slide 3

Slide 3 text

今日のテーマ IPAのデータベーススペシャリスト試験問題をもとに、 ● PostgreSQLやMySQL ● 関連/派生プロダクト での機能利用例を参照しながら、 ● 実務と共通する部分 ● 実務とは違う部分 を読み解いていきます 前回(3/6)分スライド : https://twitter.com/hmatsu47/status/1234490770134007809 ※今日の範囲は、仕様面では「違う部分」が多いです 3

Slide 4

Slide 4 text

伝えたいこと(再掲) ● IPA試験の問題も、使い方次第で実務に役立ちます ● 実務とは違うところもあるので、その違いを意識して役立てま しょう ○ RDBMSによって実装されている機能は異なります ○ 同じ機能が実装されていても、仕様や挙動が違うこともあります ● とはいえ、このセッションでは厳密なことは説明しないので、 雰囲気がわかればOKです ※一部文字が小さいページがあります  スライドを手元にダウンロードしてお使いください  https://twitter.com/hmatsu47/status/1239176917732839426 4

Slide 5

Slide 5 text

おしながき ● 平成31年春期試験・午後2問1の概要(再掲) ● ④テーブルパーティショニング ○ 試験問題とPostgreSQL/MySQLを比較する ○ PostgreSQLとMySQLで確認してみる ● ⑤パラレルクエリ ○ 試験問題とPostgreSQLを比較する ○ PostgreSQLで確認してみる ● ⑥クラスタリング ○ 試験問題とMySQL/PostgreSQL関連(派生)プロダクトを比較する ○ RDBMSクラスタリングの問題点とNewSQLについて 5

Slide 6

Slide 6 text

平成31年春期試験・午後2問1の概要(再掲) ● データベースの実装、設計(=物理設計)の問題 ● 銀行の窓口端末のログを分析して事務手続やアプリケーション ソフトウェアの改善に役立てるために、新たな分析システムを 構築することになった ● 木構造をもつログデータを効率よく扱いたい ● 性能面を考えて、テーブルのパーティショニングやクラスタ化 を検討したい 6

Slide 7

Slide 7 text

平成31年春期試験・午後2問1の概要(再掲) ● データベースの実装、設計(=物理設計)の問題 ● 銀行の窓口端末のログを分析して事務手続やアプリケーション ソフトウェアの改善に役立てるために、新たな分析システムを 構築することになった ● 木構造をもつログデータを効率よく扱いたい ● 性能面を考えて、テーブルのパーティショニングやクラスタ化 を検討したい ○ パラレルクエリを絡めて 7

Slide 8

Slide 8 text

④テーブルパーティショニング テーブルパーティショニングとは? ● テーブル内のデータを分割して保持する機能 ● うまく使うと処理を高速化できる 処理を高速化できるケース ● インデックスが効きづらいデータの絞り込み処理(刈り込み) ● 分割したテーブルを別のハードウェア(物理)に配置 ● パーティション単位での一括削除 8

Slide 9

Slide 9 text

④テーブルパーティショニング 試験問題(平成31年春期試験・午後2問1)P.10~11〔RDBMSの主な仕様〕より抜粋 9

Slide 10

Slide 10 text

④テーブルパーティショニング PostgreSQL 12の場合 ● パーティションの種類(区分方法)は3種類 ○ RANGE レンジ(範囲) ○ LIST リスト ○ HASH ハッシュ ● 親テーブルの下に子テーブルを作成する形でパーティショニングを行う ● サブパーティションも作成可能 ● PostgreSQL 11.5文書/5.10. テーブルのパーティショニング https://www.postgresql.jp/document/11/html/ddl-partitioning.html ● PostgreSQLインサイド(富士通)/パーティショニングの概要 https://www.fujitsu.com/jp/products/software/resources/feature-stories/postgres/article-index/partitioning-overview/ 10

Slide 11

Slide 11 text

④テーブルパーティショニング MySQL 8.0の場合 ● パーティションの種類(区分方法)は4種類(バリエーション含め8種類) ○ RANGE [COLUMNS] レンジ(範囲) ○ LIST [COLUMNS] リスト ○ [LINEAR] HASH ハッシュ(列または式) ○ [LINEAR] KEY キー(キー列) ○ COLUMNS : 複数列を使用して区分 ○ LINEAR : 線形二乗アルゴリズムを使用して区分 ● パーティションの下にサブパーティションを作成することができる ● MySQL 8.0 Reference Manual/23.2 Partitioning Types https://dev.mysql.com/doc/refman/8.0/en/partitioning-types.html 11

Slide 12

Slide 12 text

④テーブルパーティショニング 試験問題(平成31年春期試験・午後2問1)P.10~11〔RDBMSの主な仕様〕より抜粋 ※(5)はパラレルクエリの説明(後述) 12

Slide 13

Slide 13 text

④テーブルパーティショニング PostgreSQL 12/MySQL 8.0の場合 ● (5)のパラレルクエリを除いて試験問題とほぼ同じ ● WHERE句の条件指定でパーティションの刈り込み(Pruning)が可能 ○ 特にパーティションキーのカーディナリティが低い(小さい)場合に有効 ○ 主キーやインデックスで十分に絞り込める場合はあまり意味がない ● パーティションを削除することでDELETE文よりも高速な行削除が可能 ○ MySQLではALTER TABLE テーブル名 DROP PARTITION パーティション名 ■ MySQL 8.0 Reference Manual/23.3 Partition Management https://dev.mysql.com/doc/refman/8.0/en/partitioning-management.html ○ PostgreSQLではDROP TABLE 子テーブル名 13

Slide 14

Slide 14 text

④テーブルパーティショニング カーディナリティとは ● カラム(列)値のばらつき(値が何種類あるか?) ○ [例1] 0と1 : 2 ○ [例2] 1~10 : 10 ● カーディナリティが高い(大きい)列ほどインデックスで絞り込みやすい ○ カーディナリティが2、かつ偏りがない→インデックスでは半分にしか絞り込めない ■ インデックス→データ行の順にアクセスするよりもデータ行を直接フルスキャンしたほうが効率的 ○ 例外として、カーディナリティが低くても値の偏りが大きければインデックスも有効 https://qiita.com/hmatsu47/items/2d44c173a9114fd06853 【注】ER図におけるリレーションのカーディナリティ(多重度)とは別概念 14

Slide 15

Slide 15 text

④テーブルパーティショニング PostgreSQL 12の例(レンジパーティショニング) 15 ● 年別のパーティション+範囲外 用のデフォルトパーティション (2015年~2020年・各24,000行) ● 年単位のデータ取得が高速に ● 過去分を年単位で削除する場合 も高速に

Slide 16

Slide 16 text

④テーブルパーティショニング PostgreSQL 12の例(レンジパーティショニング) 16 postgres=# CREATE DATABASE partition_test; CREATE DATABASE postgres=# \c partition_test You are now connected to database "partition_test" as user "postgres". partition_test=# CREATE TABLE log_record ( partition_test(# log_id SERIAL NOT NULL, partition_test(# log_datetime TIMESTAMP NOT NULL, partition_test(# log_text VARCHAR(500) NOT NULL partition_test(# ) partition_test-# PARTITION BY RANGE (log_datetime); CREATE TABLE partition_test=# CREATE TABLE log_record_default PARTITION OF log_record DEFAULT; CREATE TABLE partition_test=# CREATE TABLE log_record_2015 PARTITION OF log_record partition_test-# FOR VALUES FROM ('2015-01-01 00:00:00') TO ('2016-01-01 00:00:00'); CREATE TABLE 日時(タイムスタンプ)で パーティショニングを試す ↓範囲外はデフォルトパーティション

Slide 17

Slide 17 text

④テーブルパーティショニング PostgreSQL 12の例(レンジパーティショニング) 17 partition_test=# CREATE TABLE log_record_2016 PARTITION OF log_record partition_test-# FOR VALUES FROM ('2016-01-01 00:00:00') TO ('2017-01-01 00:00:00'); CREATE TABLE partition_test=# CREATE TABLE log_record_2017 PARTITION OF log_record partition_test-# FOR VALUES FROM ('2017-01-01 00:00:00') TO ('2018-01-01 00:00:00'); CREATE TABLE partition_test=# CREATE TABLE log_record_2018 PARTITION OF log_record partition_test-# FOR VALUES FROM ('2018-01-01 00:00:00') TO ('2019-01-01 00:00:00'); CREATE TABLE partition_test=# CREATE TABLE log_record_2019 PARTITION OF log_record partition_test-# FOR VALUES FROM ('2019-01-01 00:00:00') TO ('2020-01-01 00:00:00'); CREATE TABLE partition_test=# ALTER TABLE log_record ADD PRIMARY KEY (log_id, log_datetime); ALTER TABLE (データINSERT) ↑主キーにパーティションキーを含める

Slide 18

Slide 18 text

④テーブルパーティショニング PostgreSQL 12の例(レンジパーティショニング) 18 postgres=# CREATE DATABASE no_partition_test; CREATE DATABASE partition_test=# \c no_partition_test You are now connected to database "no_partition_test" as user "postgres". no_partition_test=# CREATE TABLE log_record ( no_partition_test(# log_id SERIAL NOT NULL, no_partition_test(# log_datetime TIMESTAMP NOT NULL, no_partition_test(# log_text VARCHAR(500) NOT NULL no_partition_test(# ); CREATE TABLE no_partition_test=# ALTER TABLE log_record ADD PRIMARY KEY (log_id); ALTER TABLE no_partition_test=# CREATE INDEX ON log_record (log_datetime); CREATE INDEX (データINSERT) 比較用に非パーティショニング  のテーブルも用意する 全く同じデータをINSERTする

Slide 19

Slide 19 text

④テーブルパーティショニング PostgreSQL 12の例(SELECTの場合) 19 partition_test=# EXPLAIN VERBOSE SELECT COUNT(*) FROM log_record partition_test-# WHERE log_datetime BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 23:59:59'; QUERY PLAN --------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------- Aggregate (cost=2135.00..2135.01 rows=1 width=8) Output: count(*) -> Seq Scan on public.log_record_2019 (cost=0.00..2075.00 rows=24000 width=0) Filter: ((log_record_2019.log_datetime >= '2019-01-01 00:00:00'::timestamp without time zone) AND (log _record_2019.log_datetime <= '2019-12-31 23:59:59'::timestamp without time zone)) (4 rows) partition_test=# \timing Timing is on. partition_test=# SELECT COUNT(*) FROM log_record partition_test-# WHERE log_datetime BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 23:59:59'; count ------- 24000 (1 row) Time: 5.854 ms 2019年のパーティションから検索されている

Slide 20

Slide 20 text

④テーブルパーティショニング PostgreSQL 12の例(SELECTの場合) 20 no_partition_test=# EXPLAIN VERBOSE SELECT COUNT(*) FROM log_record no_partition_test-# WHERE log_datetime BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 23:59:59'; QUERY PLAN --------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------- Aggregate (cost=2638.89..2638.90 rows=1 width=8) Output: count(*) -> Index Only Scan using log_record_log_datetime_idx on public.log_record (cost=0.42..2576.84 rows=24821 w idth=0) Output: log_datetime Index Cond: ((log_record.log_datetime >= '2019-01-01 00:00:00'::timestamp without time zone) AND (log_ record.log_datetime <= '2019-12-31 23:59:59'::timestamp without time zone)) (5 rows) (中略) no_partition_test=# SELECT COUNT(*) FROM log_record no_partition_test-# WHERE log_datetime BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 23:59:59'; count ------- 24000 (1 row) Time: 7.361 ms インデックスで絞り込まれている パーティショニングのほうが若干速い

Slide 21

Slide 21 text

④テーブルパーティショニング PostgreSQL 12の例(一括削除の場合) 21 partition_test=# DROP TABLE log_record_2015; DROP TABLE Time: 7.023 ms partition_test=# SELECT COUNT(*) FROM log_record partition_test-# WHERE log_datetime BETWEEN '2015-01-01 00:00:00' AND '2015-12-31 23:59:59'; count ------- 0 (1 row) no_partition_test=# DELETE FROM log_record no_partition_test-# WHERE log_datetime BETWEEN '2015-01-01 00:00:00' AND '2015-12-31 23:59:59'; DELETE 24000 Time: 123.978 ms no_partition_test=# SELECT COUNT(*) FROM log_record no_partition_test-# WHERE log_datetime BETWEEN '2015-01-01 00:00:00' AND '2015-12-31 23:59:59'; count ------- 0 (1 row) パーティショニングの場合は子テーブルをDROPする パーティショニングを利用してDROPしたほうが速い 非パーティショニングの場合はDELETEする

Slide 22

Slide 22 text

④テーブルパーティショニング MySQL 8.0の例(ハッシュパーティショニング) 22 ● flag=0と1の行 が半々で存在 (それぞれ10万行) ● COUNTを取る ● UPDATEする

Slide 23

Slide 23 text

④テーブルパーティショニング MySQL 8.0の例(ハッシュパーティショニング) 23 mysql> CREATE DATABASE partition_test; Query OK, 1 row affected (0.00 sec) mysql> USE partition_test Database changed mysql> CREATE TABLE flag_test ( -> id INT NOT NULL AUTO_INCREMENT, -> str VARCHAR(500) NOT NULL, -> flag INT NOT NULL, -> PRIMARY KEY (id, flag) -> ) -> PARTITION BY HASH(flag) -> PARTITIONS 2; Query OK, 0 rows affected (0.04 sec) (データINSERT) flag=0または1しかないテーブル  でパーティショニングを試す

Slide 24

Slide 24 text

④テーブルパーティショニング MySQL 8.0の例(ハッシュパーティショニング) 24 mysql> CREATE DATABASE no_partition_test; Query OK, 1 row affected (0.01 sec) mysql> USE no_partition_test Database changed mysql> CREATE TABLE flag_test ( -> id INT NOT NULL AUTO_INCREMENT, -> str VARCHAR(500) NOT NULL, -> flag INT NOT NULL, -> PRIMARY KEY (id), -> INDEX idx_flag (flag) -> ); Query OK, 0 rows affected (0.02 sec) (データINSERT) 比較用に非パーティショニング  のテーブルも用意する 全く同じデータをINSERTする

Slide 25

Slide 25 text

④テーブルパーティショニング MySQL 8.0の例(SELECTの場合) 25 mysql> EXPLAIN SELECT COUNT(*) FROM partition_test.flag_test WHERE flag=1\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: flag_test partitions: p1 type: index possible_keys: PRIMARY key: PRIMARY key_len: 8 ref: NULL rows: 96444 filtered: 10.00 Extra: Using where; Using index 1 row in set, 1 warning (0.00 sec) 約10万行=全体の半分 (サンプリング統計なので誤差あり)

Slide 26

Slide 26 text

④テーブルパーティショニング MySQL 8.0の例(SELECTの場合) 26 mysql> EXPLAIN SELECT COUNT(*) FROM no_partition_test.flag_test WHERE flag=1\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: flag_test partitions: NULL type: ref possible_keys: idx_flag key: idx_flag key_len: 4 ref: const rows: 96444 filtered: 100.00 Extra: Using index 1 row in set, 1 warning (0.00 sec) こちらも約10万行=全体の半分

Slide 27

Slide 27 text

④テーブルパーティショニング MySQL 8.0の例(SELECTの場合) 27 mysql> SELECT COUNT(*) FROM partition_test.flag_test WHERE flag=1\G *************************** 1. row *************************** COUNT(*): 100000 1 row in set (0.03 sec) mysql> SELECT COUNT(*) FROM no_partition_test.flag_test WHERE flag=1\G *************************** 1. row *************************** COUNT(*): 100000 1 row in set (0.01 sec) SELECTでは誤差の範囲 (むしろパーティショニングのほうが遅い)

Slide 28

Slide 28 text

④テーブルパーティショニング MySQL 8.0の例(UPDATEの場合) 28 mysql> EXPLAIN UPDATE partition_test.flag_test SET flag=0 WHERE flag=1\G *************************** 1. row *************************** id: 1 select_type: UPDATE table: flag_test partitions: p1 type: index possible_keys: NULL key: PRIMARY key_len: 8 ref: NULL rows: 96444 filtered: 100.00 Extra: Using where; Using temporary 1 row in set, 1 warning (0.00 sec) 約10万行=全体の半分 (変化なし)

Slide 29

Slide 29 text

④テーブルパーティショニング MySQL 8.0の例(UPDATEの場合) 29 mysql> EXPLAIN UPDATE no_partition_test.flag_test SET flag=0 WHERE flag=1\G *************************** 1. row *************************** id: 1 select_type: UPDATE table: flag_test partitions: NULL type: index possible_keys: idx_flag key: PRIMARY key_len: 4 ref: NULL rows: 192888 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec) こちらは約20万行=フルスキャンに

Slide 30

Slide 30 text

④テーブルパーティショニング MySQL 8.0の例(UPDATEの場合) 30 mysql> UPDATE partition_test.flag_test SET flag=0 WHERE flag=1\G Query OK, 100000 rows affected (6.26 sec) Rows matched: 100000 Changed: 100000 Warnings: 0 mysql> UPDATE no_partition_test.flag_test SET flag=0 WHERE flag=1\G Query OK, 100000 rows affected (9.90 sec) Rows matched: 100000 Changed: 100000 Warnings: 0 UPDATEでは明確な差が出た (パーティショニングのほうが速い)

Slide 31

Slide 31 text

④テーブルパーティショニング まとめ ● テーブル内のデータを分割保持するのがテーブルパーティショニング ● 高速化できるケースは限られるのでご利用は計画的に ○ 高速化できても劇的に速くなるわけではない ● 特にMySQLの場合は性能面のメリットがそれほど大きくない ○ カーディナリティが低い条件での更新を多用するなら… ● パーティション単位の一括削除が必要なら検討する価値あり? 31

Slide 32

Slide 32 text

⑤パラレルクエリ パラレルクエリとは ● 1つのクエリ(SQL)の処理を分割して並列で処理する機能 ● データ/インデックスのスキャンを並列で行う ● MySQL 8.0ではごく一部の限られたSQLのみ対応 ○ SELECT COUNT(*) と CHECK TABLE ● 試験問題とは違い、テーブルパーティショニングに関係なく使える ○ 1つのテーブルでも有効 ● PostgreSQL 11.5文書/第15章 パラレルクエリ https://www.postgresql.jp/document/11/html/parallel-query.html 32

Slide 33

Slide 33 text

⑤パラレルクエリ PostgreSQL 12の例(さきほどの非パーティショニングテーブルにて) 33 ● 2つのWorker プロセスが並 列でデータ行 を取得

Slide 34

Slide 34 text

⑤パラレルクエリ PostgreSQL 12の例(さきほどの非パーティショニングテーブルにて) 34 no_partition_test=# SET max_parallel_workers_per_gather=2; SET no_partition_test=# EXPLAIN VERBOSE SELECT log_datetime, COUNT(*) FROM log_record GROUP BY log_datetime; QUERY PLAN ---------------------------------------------------------------------------------------------------------- Finalize GroupAggregate (cost=13902.96..13921.21 rows=72 width=16) Output: log_datetime, count(*) Group Key: log_record.log_datetime -> Gather Merge (cost=13902.96..13919.77 rows=144 width=16) Output: log_datetime, (PARTIAL count(*)) Workers Planned: 2 -> Sort (cost=12902.94..12903.12 rows=72 width=16) Output: log_datetime, (PARTIAL count(*)) Sort Key: log_record.log_datetime -> Partial HashAggregate (cost=12900.00..12900.72 rows=72 width=16) Output: log_datetime, PARTIAL count(*) Group Key: log_record.log_datetime -> Parallel Seq Scan on public.log_record (cost=0.00..12600.00 rows=60000 width=8) Output: log_id, log_datetime, log_text (14 rows) Time: 0.597 ms Workerプロセスを2に (デフォルトで有効)

Slide 35

Slide 35 text

⑤パラレルクエリ PostgreSQL 12の例 35 no_partition_test=# SET max_parallel_workers_per_gather=0; SET Time: 0.206 ms no_partition_test=# EXPLAIN VERBOSE SELECT log_datetime, COUNT(*) FROM log_record GROUP BY log_datetime; QUERY PLAN -------------------------------------------------------------------------------- HashAggregate (cost=14160.00..14160.72 rows=72 width=16) Output: log_datetime, count(*) Group Key: log_record.log_datetime -> Seq Scan on public.log_record (cost=0.00..13440.00 rows=144000 width=8) Output: log_id, log_datetime, log_text (5 rows) Time: 0.443 ms Workerプロセスを0に(パラレルクエリ無効) このケースでは実際のSQL実行でも パラレルクエリのほうが遅い(サーバスペックの問題)

Slide 36

Slide 36 text

⑤パラレルクエリ まとめ ● 1つのクエリの処理を分割して並列で処理するのがパラレルクエリ ● MySQL 8.0では(ほぼ)利用できない ○ 今後に期待 ● PostgreSQL 12ではデフォルトで有効になっている ○ あまり気にせずに使える ○ サーバのスペックによってはかえって遅くなることもあるのでその場合は無効にする ● パーティショニングと併用しなくても使える 36

Slide 37

Slide 37 text

⑥クラスタリング 試験問題(平成31年春期試験・午後2問1)P.11〔RDBMSの主な仕様〕より抜粋 37

Slide 38

Slide 38 text

⑥クラスタリング クラスタリングとは ● 複数のノードでクエリ(SQL)を処理/データを保存する構成 シェアードエブリシングとシェアードナッシング ● シェアードエブリシング:データ保存先のストレージを全ノードで共有 ○ Oracle RACなど ● シェアードナッシング :データ保存先のストレージを共有しない ○ 一般的にはこちらが多い シャーディング(分散)とレプリケーション(複製) ● シャーディング :データを行単位または列単位で分割して保存 ● レプリケーション:ノード間でデータを複製して保存(同期/非同期) 38

Slide 39

Slide 39 text

⑥クラスタリング 試験問題(平成31年春期試験・午後2問1)P.11〔RDBMSの主な仕様〕より抜粋 一般的なクラスタリングでは ● アクセス先の振り分けと実際の処理は別ノードで処理 ○ プロキシ/ルーターで振り分け(主にレプリケーション利用の場合) ○ コーディネーターノードがワーカーノードに振り分け(シャーディングの場合) 39

Slide 40

Slide 40 text

⑥クラスタリング プロキシで振り分け 40 ● 主にレプリケーションを利用 するクラスタで採用 ○ 例:MySQL+ProxySQL ● Proxy自体も冗長化する ○ SPOF防止 ● セキュリティ目的の配置も ○ Firewall(不正クエリ防止) ○ クエリログ採取

Slide 41

Slide 41 text

⑥クラスタリング ルーターで振り分け ● 主にレプリケーションを利用するクラスタで採用 ○ 例:MySQL InnoDB Cluster, InnoDB ReplicaSet ● アクセス元のWebサーバ等にルーターを同居させて振り分ける 41

Slide 42

Slide 42 text

⑥クラスタリング シャーディング:コーディネーターノードで振り分け ● シャーディングであっても、一つまたは複数のワーカーノードに同じデータ をレプリケーションできるようになっていることが多い 42 ● コーディネーターノード がワーカーノードに振り 分け ○ 例:Citus、Vitess ● コーディネーターノード も冗長化する ○ SPOF防止

Slide 43

Slide 43 text

⑥クラスタリング 参考情報(レプリケーション・シャーディング) ● ProxySQL(公式)※プロキシのみ https://www.proxysql.com/ ● MySQL InnoDB Cluster(MySQL公式+Smart Style) https://dev.mysql.com/doc/refman/8.0/en/mysql-innodb-cluster-userguide.html https://www.s-style.co.jp/blog/2018/11/2722/ ● Citus(Microsoft Azure公式+篠田さんスライド) https://docs.microsoft.com/ja-jp/azure/postgresql/concepts-hyperscale-nodes https://www.slideshare.net/noriyoshishinoda/lets-scaleout-postgresql-using-citus-japanese-123590324 ● Vitess(公式) https://vitess.io/ 43

Slide 44

Slide 44 text

⑥クラスタリング Citus(PostgreSQLベースのシャーディングクラスタ) ● Microsoftが開発元のCitus Data社を買収 ● Azure Database for PostgreSQL - Hyperscale (Citus) としてサービス提供 https://azure.microsoft.com/ja-jp/services/postgresql/ ● Microsoft社内でWindows Updateのログデータ分析に利用されている https://www.atmarkit.co.jp/ait/articles/1911/06/news003.html Vitess(MySQLベースのシャーディングクラスタ) ● YouTube内部で利用するために開発 ● Cloud Native Computing Foundation (CNCF) がプロジェクトをホスト ○ 2019/11にGraduationをアナウンス https://www.cncf.io/announcement/2019/11/05/cloud-native-computing-foundation-announces-vitess-graduation/ 44

Slide 45

Slide 45 text

⑥クラスタリング レプリケーションを利用したクラスタリングの問題点 ● レプリケーションラグが発生する(非同期レプリケーションの場合) ● 更新性能が悪くなる(同期レプリケーションの場合) ● 更新性能がスケールしない ○ マルチマスター構成にすると更新の競合でかえって性能が下がる シャーディング方式のクラスタリングの問題点 ● レプリケーションを併用しない場合、データ冗長化ができない ○ 一部のSQLが実行できないなど、機能面の制約もある ● レプリケーションを併用しないとシャードをまたぐ処理が遅い場合がある ○ 通信処理が必要な分オーバーヘッドが発生する(JOINなど/試験問題と同じ) ● シャードの再構成時に性能が低下しやすい 45

Slide 46

Slide 46 text

⑥クラスタリング 最近の流れ:NewSQL ● 更新を含めた性能のスケールと、データの整合性を両立 ● 地理冗長性も意識 主なNewSQL(と呼ばれるもの) ● Google Spanner https://cloud.google.com/spanner?hl=ja ● CockroachDB https://www.cockroachlabs.com/product/ ● YugaByteDB https://www.yugabyte.com/ ● TiDB(分散KVS「TiKV」をバックエンドに利用したSQL対応DB) https://pingcap.com/en/ 46

Slide 47

Slide 47 text

⑥クラスタリング おまけ 47 おさじ(@pypypyo14)さんの ツイートより引用 ● 噂(?)のCockroachDBの… ● 黄緑と緑と黒でよかった(?) ● 茶色とこげ茶と黒だったら嫌だ

Slide 48

Slide 48 text

⑥クラスタリング 参考情報(NewSQL) ● Spanner(kumagiさん) https://qiita.com/kumagi/items/7dbb0e2a76484f6c522b ● 2020年現在のNewSQLについて(tzkobaさん) https://qiita.com/tzkoba/items/5316c6eac66510233115 ● NewSQLのコンポーネント詳解(tzkobaさん) https://qiita.com/tzkoba/items/3e875e5a6ccd99af332f 48

Slide 49

Slide 49 text

まとめ ● テーブルパーティショニング:テーブル内のデータを分割保持 ○ 有効なケースはかなり限られる ○ パーティション単位での一括削除が高速 ● パラレルクエリ:クエリを並列処理して高速化 ○ 通常はパーティショニングと併用しなくても利用可能 ● クラスタリング:複数ノードでクエリを処理 ○ レプリケーションを利用したクラスタリングとシャーディングがある ○ レプリケーションでは読み取り整合性と書き込み性能向上の問題がある ○ シャーディングではノードまたぎの処理性能と再構成の問題がある ○ 書き込み性能向上などを目指して進化(NewSQL) 49