Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【DB】テーブルのサブタイプ

RDBMSにおけるテーブルの継承

RDBMSでは、データを格納するテーブルに継承関係を定義することができます。例えば文房具屋さんが店舗で扱う商品を管理するために、書籍テーブルや文具テーブルなどを作成することができます。しかし、書籍や文具は商品であるため、商品名や商品価格などの属性が重複してしまいます。

そこで、テーブル間に継承関係をもたせ、各テーブルで共通する属性は一つにまとめて別途定義します。このときの共通する属性を持つテーブルをスーパータイプと呼びます。また、書籍であればISBN番号など、個々の具体的なテーブルに出現する属性をまとめたテーブルをサブタイプと呼びます。

一般に、実世界の処理を反映するのはサブタイプのテーブルなので、例えば新しい書籍が入荷されたときはサブタイプである書籍テーブルの行を追加します。書籍情報はISBN番号だけでなく、商品名や商品価格も持つので、スーパータイプへの行追加も必要です。

スーパータイプに行が追加されたときの、サブタイプへの行追加のやり方によって、サブタイプは

  • 排他的サブタイプ
  • 共存的サブタイプ

に分類されます。

排他的サブタイプ

排他的サブタイプは、スーパータイプに行が追加されたとき、いずれかのサブタイプにのみ行追加を行います。

先程の例でいえば、書籍「ハリーポッター」が入荷されたときは、書籍テーブルと商品テーブルに行が追加されます(文具テーブルはそのまま)。

共存的サブタイプ

文具テーブルが、仮に鉛筆テーブルと消しゴムテーブルに分かれていたとします(このようなやり方をあまり聞いたことはありませんが)。

もし「鉛筆と消しゴムのセット」のような、鉛筆でありながら消しゴムにも含まれる商品を両方のテーブルで管理したい場合があるとします。

このとき、上位の文具テーブル(と商品テーブル)に行が追加されるとともに、鉛筆テーブル、そして消しゴムテーブルにも行が追加されます。

この鉛筆テーブルと消しゴムテーブルのような、互いが排他的でないくなるサブタイプを共存的サブタイプと呼びます。共存的サブタイプを採用する場合、スーパータイプの行が発生したときにサブタイプの双方に行が発生します。

【DB】分散DBシステムのテーブル結合

分散RDBMSシステムでのテーブル結合

分散DBシステムでは、物理的には複数のDBにデータを分散させているにもかかわらず、あたかも一つのDBにアクセスしているかのように振る舞います(位置透過性)。例えばSQLで複数のテーブルを結合しつつ問い合わせを行う時、各テーブルが物理的に離れた場所のDBにあっても、各DBが互いに連携することで整合性の取れた結果を取得することができます。

遠隔地にあるDB同士が互いの持つデータをやり取りする場合、出来る限り通信負荷を削減したいものです。分散RDBMSシステムでテーブル結合を行う場合には、通信負荷軽減のため以下のような結合法を採用します。

  • セミジョイン法
  • 入れ子ループ法
  • マージジョイン法

セミジョイン法

例として、以下の二つのテーブルを結合するとします。

商品テーブル
商品ID 商品名 価格
1 チョコレート 200
2 キャラメル 50
3 キャンディ 100
伝票テーブル
伝票ID 顧客ID 商品ID 個数
1 001 1 10
2 001 2 20
3 002 1 30

SQLは以下のとおりです。

SELECT 商品.商品ID, 伝票.伝票ID
FROM  商品, 伝票
WHERE 商品.商品ID = 伝票.伝票ID

このとき、セミジョイン法ではDBが検索対象となった列の値のみを他方のDBに送信し、値を受け取ったDBはマッチする結果行を元のDBへ返戻します。

f:id:rennnosukesann:20180408233805p:plain

上のSQLの結合に必要な列は商品IDだけなので、大阪DBは商品IDのみからなる部分テーブルを名古屋DBに送り、名古屋DBは送られた部分テーブルと伝票テーブルを結合します。結合結果から必要となる列のみからなるテーブルを射影し、大阪DBに送り直しています。このように特定列の値のみを送受信することで、通信量を削減しています。

入れ子ループ法

入れ子ループ法では、DBがテーブル行を一行ずつ送信しながら、他方のDBによる結合結果を受け取る方式です。

f:id:rennnosukesann:20180408233819p:plain

送信元では必要な列の射影を行わず、とにかく一行ずつ送信して、相手に結合結果を返してもらいます。

マージジョイン法

マージジョイン法は、他方のDBにソート済みのテーブルデータを送信してもらった上で結合を行います。

f:id:rennnosukesann:20180408234412p:plain

結合回数は少なくなりますが、データ送信量は先に紹介した手法と比較して大きいです。

【DB】分散DBシステムの透過性

分散DBシステムとは

分散DBシステムは、複数のDBが地理的に遠隔地にある場合にネットワークを経由して協調処理をさせるシステムを指します。分散DBシステムをサービスとして提供する場合、利用者にはあたかも一つのDBにアクセスしているように見えるようにし、物理的なDBが複数に分散していることを意識させないことが重要です。この分散状態を意識させないことを分散DBシステムにおける「透過性」と呼び、透過性はさらに以下のような項目に分類できます。

  • アクセス透過性
  • 位置透過性
  • 移動透過性
  • 分割透過性
  • 重複透過性
  • 規模透過性
  • 並行透過性

アクセス透過性

利用者がネットワーク経由で接続されている全てのDBのデータに同一の方法でアクセスできる性質を指します。例えば、分散DBシステムに参加する個々のDBの仕様が異なっても、分散DBシステム上のデータへのアクセス方法が同一であれば、アクセス透過性を持つといえます。

位置透過性

DBが地理的に移動しても、利用者がシステムの位置を意識せず利用できる性質。

移動透過性

データの格納場所が変更されても、利用者がデータの場所変更を意識せずに利用できる性質。大阪のDBから名古屋のDBへデータが移動されても、分散DBシステム上アプリケーション内ではディレクトリ位置が変更されていない・・・など。

分割透過性

一つのデータが複数のDBに分割して格納されていても、利用者はあたかも一つのデータが一箇所にあるものとしてアクセスできる性質。テーブルAが東京にあり、テーブルBが北海道にあっても、分散DBシステムの利用者からはそれらを結合したテーブルを利用できる、など。

重複透過性

一つのデータが複数のDBに重複して置かれていても、利用者はデータが一つしか無いものとして利用できる性質。

規模透過性

DB機能を提供するマシンやアプリケーションの構成に関係なく、システム規模を変更できる性質。

並行透過性

利用者が、複数のDBに対し同時並行的にDB操作を行うことができる性質。

Kibanaでログデータの可視化を行う

Kibanaとは

f:id:rennnosukesann:20180406220839p:plain:w300

KibanaはElastic社が提供するデータ可視化ツールです。 Elastic社は文書全文検索データベースであるElasticseatchをサービスとして提供していますが、Kibanaはこのデータベース上のデータを分析しやすいように可視化してくれます。

Kibanaをインストール

(環境: Mac OS X High Sierra

まずはKibanaをインストールします。 Kibana公式サイトより、右上のDownloadボタンをクリックします。

f:id:rennnosukesann:20180407154110p:plain

遷移先のページでパッケージダウンロードリンクがあるので、自分が使用しているOSにあったものをクリックしてダウンロードします。今回はMacOSを使用しているので、「MAC」のリンクをクリック。

f:id:rennnosukesann:20180407154119p:plain

ダウンロードしたパッケージを展開します。

Erasticserchを使う

Erasticsearchとは

f:id:rennnosukesann:20180407163639j:plain:w400

ErasticsearchはErastic社が提供するオープンソース全文検索エンジンです。
Javaで構成されており、Apatch Lucineと呼ばれる検索エンジンを基盤としています。

自分は業務内でアプリケーションサーバのログデータを収集・解析しているのですが、
Erasticsearch(+Kibana)と連携してデータの収集と可視化を行なっているので、今回はそのための学習をかねて実際にErasticsearchをいじってみます。

Erasticsearchのインストール

(環境: Mac OS X High Sierra)

早速インストールしていきます。 Erastic公式サイトのErasticsearch専用ページ右上に「download」ボタンがあるのでクリック。

f:id:rennnosukesann:20180407163140p:plain

クリックすると、パッケージがダウンロードできる画面に遷移します。
今回はzipファイルをダウンロードしてみます。

f:id:rennnosukesann:20180407163159p:plain

解凍します。

【Angular】スクロールイベントを監視するDirective

AngularJSでスクロールイベントに伴う処理を実装したかったのですが、スクロールイベントの監視をビジネスロジックに記述したくなかったので、画面のスクロールイベントを監視させるAngularのDirectiveを作成しました。

Directive

angular.module('App')
.directive('ngScroll',[
  '$window',
  function($window){
    return {
      scope:{
         // ng-scrollの右辺値が関数であることを指定
         // compileプロパティの関数が返す関数の引数$scopeに格納
        ngScroll : '&'
      },
      compile: function(element, attrs) {
        return function($scope, element, attrs) {
          angular.element($window).bind('scroll', function(){
            // ng-scrollの右辺値に指定した関数を呼び出し
            $scope.ngScroll($window);
          });
        }
      }
    }
}]);

Controller

angular.module('App', [])
.controller('MainController', [
  '$scope',
  function($scope){
      $scope.onScroll = function() {
          console.log('scroll');
      }
}]);

HTML

<body ng-controller='MainController'>
    <div ng-scroll="onScroll()"></div>
</body>

directiveを定義したタグを含むページのスクロールを監視できます。
これで、ビジネスロジック側はスクロール時の挙動定義に集中できます。