Mercurial > hg > Papers > 2017 > tatsuki-master
view databases.tex @ 29:92d6882c1143
add svg
author | tatsuki |
---|---|
date | Sun, 12 Feb 2017 18:55:36 +0900 |
parents | 4365c210d1cb |
children |
line wrap: on
line source
%もう少し詳しく書く \chapter{既存のデータベース} 本章では、既存のデータベースの例として、PostgreSQL・MongoDB・Cassandra・当研究室で開発しているJungle について記述する。 \section{PostgreSQL} PostgreSQLは、列と行からなる2次元のテーブルにより実装されるデータベースである。 厳密な型を持つデータベースであり、きちんと設計を行えば、柔軟なクエリを用いてどんな検索にも対応できる力を持つ。 データベースへのアクセスは、SQLを用いて行う。 データの格納を行う際は、まずテーブルのデータの型と・制約を定義する。 テーブルの定義は{\tt CREATE TABLE}文を用いて行う。 ソースコード\ref{createTablePSQL}に{\tt int}型の{\tt id}と{\tt TEXT}型の{\tt name}を持つテーブル{\tt person}を作成するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=createTablePSQL,caption=テーブルの作成] create table person(id int,name TEXT); \end{lstlisting} %制約というのは、テーブルに値を入れる際に守らなければならない条件のことである。 %値の重複を許さない行を特定する際に用いる{\tt PRIMARY KEY}などがある。 %また、テーブル同士は{\tt PRIMARY KEY}を用いて参照を行うことが可能である。 テーブルへのデータの格納は、Insert文を用いて行う。 ソースコード\ref{insertPSQL}に、{\tt id}が{3}、{\tt name}が{kanagawa}の値を格納するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=insertPSQL,caption=データの挿入] insert into person(id,name) values(3,'kanagawa'); \end{lstlisting} テーブルにデータを格納する際にはスキーマの定義に沿ってなければならない。 もし、スキーマに反するデータを格納した場合 エラーが発生しデータの格納に失敗する。 テーブルへのデータの検索は、select文を用いて行う。 select文では、表示するデータの指定などが行える。 ソースコード\ref{selectPSQL}に、テーブル{\tt person}から{\tt name}が{\tt kanagawa}のデータのidを取得するコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=selectPSQL,caption=データの検索] select id from person where name='kanagawa'; \end{lstlisting} PostgreSQLでは、Json形式をJson・JsonBという型を用いて格納する。 Json型は、Jsonデータを文字列で格納し、JsonBはバイナリで格納する。 Json型で格納した場合、データにアクセスするたびにパースする必要がある。 %JsonのIndex を張ることが可能になっている。 % Jsonデータのアップデートは、Jsonの大きさnに対してO(n)になってしまう。 \section{MongoDB} MongoDB\cite{mongoDBDoc} は2009年に公開された NoSQL のデータベースである。 JSON フォーマットのドキュメントデータベースであり、スキーマレスと呼ばれる。 MongoDBでは、テーブルの代わりにコレクションにデータを保持する。 スキーマが無いため、事前にデータの定義を行う必要がなく、同じコレクションであっても、他のドキュメントが持っていないフィルドやデータ型をドキュメントに含めることができる。 そのためリレーショナルデータベースに比べてデータの追加・削除が行いやすい。 コレクションへのデータの格納は、{\tt insert()}を用いて行う。 ソースコード\ref{insertMongo}に、{\tt id}が{\tt 5}、{\tt name}が{\tt kanagawa}のデータをコレクション{\tt person}に挿入するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=insertMongo,caption=データの検索] db.person.insert({id:5,name:"kanagawa"}); \end{lstlisting} また、Json形式のデータは任意の深さまでネストすることが可能である。 作成したコレクションからのデータの取得は、{\tt find}を用いて行う。 ソースコード\ref{findMongo}に、{\tt id}が{\tt 5}のユーザーの{\tt name}を取得するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=findMongo,caption=データの検索] db.person.find({id:5},{name:1}); \end{lstlisting} findに引数を渡さなかった場合、コレクションの中身が全て表示される。 MongDBは、あらゆる箇所でJavaScriptを用いており、前述した{\tt insert()}・{\tt find()}といった関数もJavaScriptで実装されている。 dbですらJavaScriptのオブジェクトである。 findで使用するクエリもJavaScriptで記述できる。 MongoDBは実装にmmapを使用しているため、トランザクションを安全に行うことが難しい。 そのためデータの喪失などが発生することが知られている。 \section{Cassandra} Cassandraは2008年7月にFacebookによって開発された Key-Value なデータベースである。 Cassandraは、分散環境下では複数のノードにデータのレプリカを置くことで、データの信頼性を確保する。 いくつのノードにレプリカを置くかはレプリケーション係数を指定することで決定する。 またノードの集合をデータセンターとして管理している。 Cassandraはデータを {\tt [KeySpace][ColumnFamily][Key][Column]}\\ の4次元の連想配列で持つ。 データを格納する場合初めにKeySpaceを構築する。 KeySpaceを作る際は、データセンターの設定とレプリケーション係数の設定を同時に行う。 ソースコード\ref{createKeySpace}に単一のデータセンターにレプリケーションを一つしか持たないKeySpaceである{\tt testKeySpace}を作成するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=createKeySpace,caption=KeySpaceの作成] create keyspace testKeySpace with replication = {'class':'SimpleStrategy', 'replication_factor':1}; \end{lstlisting} KeySpaceは、PostgreSQLでいうところのデータベースに近い働きをする。 次は、作成した KeySpace に対してColumnFamily を構築する。 ColumnSpaceは、RDBでいうテーブルに似た働きをする。 ソースコード\ref{createColumnFamily}に、{\tt int}型の{\tt id}と{\tt text}型の{name}を持つColumnSpaceを作成するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=createColumnFamily,caption=ColumnFamilyの作成] create table person (id int PRIMARY KEY, name text); \end{lstlisting} また、ColumnSpaceの定義を行う際最低1つKeyに値を特定するためのPRIMARY KEY を指定する必要がある。 作成したColumnFamily への値の挿入は、insert文を用いて行う。 ソースコード\ref{insertCassandra}に、{\tt id}が{1}、{\tt name}が{\tt kanagawa}のデータを挿入するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=insertCassandra,caption=ColumnFamilyの作成] insert into person(id,name) values(1,'kanagawa'); \end{lstlisting} 作成した ColumnFamily からのデータの取得は、select文を用いて行う。 ソースコード\ref{findCas}に、{\tt id}が{\tt 1}のユーザーの{\tt name}を取得するサンプルコードを記述する。 \begin{lstlisting}[frame=lrbt,numbers=left,label=findCas,caption=ColumnFamilyの作成] select name from person where id = 1; \end{lstlisting} Cassandraはデータの読み書きをいくつのノードに行うかをConsistteency Levelで設定する。 Consistency Levelは主に、ONE、QUORAM、ALLがある。 データの複製であるレプリケーションの数をNとした場合、ONEは1つのノード、QUERUMはN/2 + 1のノード、ALLはNのノードへと読み書きを行う。 CassandraはConsistency Levelを変えることで、最新のデータを取得するかどうかを決めることができる。 しかし、最新のデータを取得するために、Consistency LevelをQUERUMやALLに変えた場合、データの読み書き時に問い合わせるノードが増えるため速度は落ちてしまう問題もある。 \section{非破壊的木構造データベースJungle} Jungleは、当研究室で開発を行っているデータベースで、Javaを用いて実装されている。 Jungleは名前付きの複数の木の集合からなり、木は複数のノードの集合で出来ている。 ノードは自身の子のリストと属性名と属性値の組でデータを持ち、データベースのレコードに相当する。 通常のレコードと異なるのは、ノードに子供となる複数のノードが付くところである。 Jungleでは、親から子への片方向の参照しか持たない。 通常のRDBと異なり、Jungleは木構造をそのまま読み込むことができる。例えば、XMLやJsonで記述された構造を、データベースを設計することなく読み込むことが可能である。 また、この木を、そのままデータベースとして使用することも可能である。しかし、木の変更の手間は木の構造に依存する。 特に非破壊木構造を採用しているJungleでは、木構造の変更の手間はO(1)からO(n)となりえる。つまり、アプリケーションに合わせて木を設計しない限り、 十分な性能を出すことはできない。逆に、正しい木の設計を行えば高速な処理が可能である。 Jungleは基本的にon memoryで使用することを考えており、一度、木のルートを取得すれば、その上で木構造として自由にアクセスして良い。 Jungleは分散データベースを構成するように設計されており、分散ノード間の通信は木の変更のログを交換することによって行われる。 持続性のある分散ノードを用いることでJungleの持続性を保証することができる。 詳しいAPIについては次章で記述する。