複数のデータベース/サーバーを使用したデータとの対話


18

私がこれまでに対処しなければならなかったプロジェクトはすべて、単一のサーバー上の単一のデータベースのみを必要としました。私は、負荷を管理するために、スケーリングする必要があるプロジェクトが複数のデータベースやサーバーにどのように移動するかについて、もっと知りたいと思っています。私は高いスケーラビリティを知っていますが、私は特にいくつかのコード例や、このテーマについてもっと読むことができる追加のリソースに興味があります。

例えば:

  • 複数のデータベース上の2つのテーブル間で結合はどのように構築されますか?(ここのコード例が役立ちます)。
  • どのテーブルがどのデータベースにあるかを追跡するための特別な戦略はありますか?
  • アプリケーションコードは、1つ以上のデータベースが複数のサーバーに分散していることを知る必要がありますか?そうでない場合、要求はどのレベルでフィルタリングされますか?
  • 1データベース/ 1サーバーのセットアップを超える時期はいつですか?これを行う必要があるのはどれくらい一般的ですか?

この質問は、データベース管理者でより適切に回答される場合があります。ただし、ここでも特に問題はないので、DBA modで確認するだけです。そこで適切であれば、移行しますか?
アダムリア

@AnnaLear-答え次第だと思います。この時点で、私はこの問題のアプリケーション側にもっと興味を持っているので、今のところ、ここでの方が良いかもしれません。
VirtuosiMedia

@AnnaLear ack、アプリ固有のコードが必要な場合はOPに同意します。
jcolebrand

回答:


13

わかりました、それを分解しましょう:

  • 複数のデータベース上の2つのテーブル間で結合はどのように構築されますか?(ここのコード例が役立ちます)。

これは非常に簡単です。SQLオブジェクトには、1〜4部の命名規則があります。

サーバー名。データベース名。スキーマ名。テーブル名

すべてのテーブルが同じ所有者/スキーマで同じデータベースの同じサーバーにある場合、最初の3つの部分を無視して、最もよく使用するものを使用できます。

Select a.*,b.* from 
tableA a inner join 
tableB b on a.col1=b.col1

テーブルの1つが別のデータベースにあり、両方がデータベースのデフォルトスキーマを使用している場合、データベースを2番目のテーブルに追加するだけです。

Select a.*,b.* from 
tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

クエリを実行しているデータベースのいずれとも異なる3番目のデータベースにいる場合は、両方のデータベース名を明示的に使用します。

Select a.*,b.* from 
databaseD..tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

異なるスキーマや所有者を使用することになった場合、それらを次の場所に追加できます。

Select a.*,b.* from 
databaseD.john.tableA a inner join 
databaseC.accounting.tableB b on a.col1 = b.col1

そして最後に、それについて非常に注意し、非常に正当な理由がある場合は、別のサーバー上の(通常は小さな)テーブルに参加できます。

Select a.* from 
databaseD.john.TableA a inner join 
ATLANTA.databaseC.accounting.tableB b on a.col1 = b.col1
  • 1データベース/ 1サーバーのセットアップを超える時期はいつですか?これを行う必要があるのはどれくらい一般的ですか?どのテーブルがどのデータベースにあるかを追跡するための特別な戦略はありますか?

これら2つが一緒になるので、これら2つを組み合わせます。ほとんどの場合、設計/ビジネス/技術的な制約によりさらに多くの使用が必要になるまで、1つのデータベースが1つのサーバーで十分であるという前提から始めても大抵は問題ありません。

したがって、最初に2番目の質問に答えるには、通常、個別のデータベースを使用する理由があるため、システムの設計がどこにあるかを知っていれば、それはかなり明白なはずです。

いつ/なぜ、単一のデータベースを越えて移動する必要があるかについて。通常、ビジネスルール、政治、および/または技術的な理由が混在しています。

たとえば、私が働いている場所では、4つのサーバーに16個のデータベースが分散しています。MainDB、ImageDB、referencetableDB、HighvolumeTransactionDB、ReportingDB、StagingDB、ProcessingDB、ArchiveDB、FinancialDBがあります。それらが異なる理由の例を挙げます:

  • FinancialDB、機密情報
  • イメージDB、特定の異なるストレージおよびリカバリ要件
  • ReferenceDB、低トランザクション、高読み取り
  • 非常に高い読み取りのReportingDBは、他の多くのデータとは異なり、さまざまな他の環境に復元/複製する必要があります
  • StagingDB、永続的なものではなく、強化されたtempdb
  • MainDB、他のすべてのDBとインターフェイスしますが、差分バックアップが必要なため、...
  • HighVolumeTransactionテーブル(比較的一時的)、バックアップを適切なサイズに保つために、独自のDBに。
  • アーカイブ、メインとレポーティングからの同じデータがたくさんありますが、保持期間が長く、データを掘り下げるクエリのヒットがより困難です。これがMain / Reportingとまだ組み合わされていると、システムが動かなくなります。

アプリケーションコードは、1つ以上のデータベースが複数のサーバーに分散していることを知る必要がありますか?そうでない場合、要求はどのレベルでフィルタリングされますか?

広い意味で、おそらくそうでしょう。少なくとも、データベース接続文字列でどのサーバーを指しているのかを知る必要があります。処理、レポート、メインなど

そこから実行するには、データベースコンテキストが必要です。通常、これはアプリケーションで最も使用されるものであり、アプリケーションの1データベース/ 1サーバー日からのオリジナルのものである可能性があります。アプリケーションは、呼び出しごとにデータベースコンテキストを明示的に切り替えることができますが、アプリケーションを変更せずにデータベースを調整することは非常に困難です。

通常の(または少なくとも、私の通常の)アプローチは、常に1つまたは2つのメインデータベースを介してアクセスすることです。

次に、必要に応じて、ストアドプロシージャを介したデータベースとのインターフェイスと組み合わせて、他のデータベースにビューを作成します。

だから説明するために:

クライアントの人口統計情報、売上データ、およびクレジット残高を取得したいとしましょう。これらはすべてMainDBの3つのテーブルに分散しています。

したがって、アプリから呼び出しを作成します。

Select c.ClientName, c.ClientAddress, s.totalSales,f.CreditBlance from
Clients c join Sales s on c.clientid = s.clientid inner join AccountReceivable f on 
c.clientid=f.clientid where c.clientid = @clientid

驚くばかり。ただし、ここでcolumnameを変更したり、テーブルの名前を変更したり移動したりするたびに、アプリコードを更新する必要があります。そのため、代わりに2つのことを行い
ます。クライアントビュー、セールスビュー、AccountReceivablesビューを作成します(Select *は使用しませんが、ここではデモしています)

Use MainDB
GO
Create view v_Clients as select * from Clients
Create view v_Sales as select * from Sales
Create view v_AccountReceivable as select * from AccountReceivable
Go

次に、ストアドプロシージャspGetClientSalesARも作成します。

Create proc spGetClientSalesAR @clientID int
as
Select c.ClientName as ClientName, 
       c.ClientAddress as ClientAddress, 
       s.totalSales as TotalSales, 
       f.CreditBlance as CreditBalance 
from
v_Clients c join v_Sales s 
    on c.clientid = s.clientid 
inner join v_AccountReceivable f 
    on c.clientid=f.clientid 
where c.clientid = @clientid

そして、あなたのアプリにそれを呼ばせます。

そのストアドプロシージャのインターフェイスを変更しない限り、スケールアウトまたはスケールアウトするためにバックエンドデータベースに対して必要なことはほとんど何でもできます。

極端な場合、古いMainDBをシェルストアドプロシージャとビューの束にすることもできます。作成したビューの下は次のようになります。

Create view v_Clients as select * from ServerX.DatabaseY.dbo.Clients
Create view v_Sales as select * from ServerQ.DatabaseP.dbo.Sales
Create view v_AccountReceivable as select * from ServerJ.DatabaseK.dbo.AccountReceivable

そして、あなたのアプリはその違いを決して知ることはありません(特に高速パイプと適切にステージングされたデータを想定しています)。

明らかにそれは極端であり、すべてがこのように計画されていると言ったら嘘をつきますが、リファクタリング中にそれを行ってもストアドプロシージャ/ビューを使用すると、アプリが謙虚な1つのデータベース/ 1つのサーバーから成長するときに、多くの柔軟性が得られます始まり。


TetonSig-答えてくれてありがとう。私はあなたに全額の報奨金を授与するために時間内に質問に戻ることができませんでした(私は旅行していました)が、質問の新しい報奨金を作成し、24時間以内にあなたに授与することができます。
VirtuosiMedia

わあ、ありがとう。感謝します。質問に答えるのはとても楽しかったです。
TetonSig

5

Webの世界で複数のデータベースサーバーに遭遇した主な方法(質問にはPHPのタグが付けられているため)は、1つの「マスター」(書き込み)データベースがあり、次に1つ以上の複製された「スレーブ」(読み取り)データベースが存在するセットアップです。データベースの書き込みは、「マスター」データベースに対して実行されます。そのデータベースの内容は、ほぼリアルタイムで「スレーブ」サーバーに複製されます。その後、クエリ(特に集中的なレポート)が「スレーブ」データベースの1つに対して実行され、それらのサーバーへの負荷がシフトされます。特定のセットアップは、読み取りは多いが書き込みは多くないアプリケーションに最適であることに留意してください。 物事を整理する唯一の方法ではありません。


3

複数のデータベース上の2つのテーブル間で結合はどのように構築されますか?(ここのコード例が役立ちます)。

そうではありません。NoSQLデータベースは「結合」をまったく行いません。RDBMSサーバー間でSQL結合を行うことができたとしても、パフォーマンスを重視するのは望ましくありません(分散コンピューティングの誤 cfを参照)。

どのテーブルがどのデータベースにあるかを追跡するための特別な戦略はありますか?

リレーショナル/ SQLデータベースでは、パーティションは通常、単一のサーバー/データベースの範囲内で、異なるディスクに配置された異なるファイルを使用して行われます。ほぼ定義上、水平スケーリングソリューションとは、すべてのデータベースにすべてのテーブルがあり、何らかのトランザクションミラーリング、レプリケーション、またはカスタムの結果整合性ソリューションがあり、すべてのデータが目的の場所に確実に到達することを意味します。

物理的にではなく論理的にデータベースを実際に分割する場合、DALまたはORMで定義されたマッピングは、どのテーブルがどのデータベースにあるかを宣言します。

NoSQLデータベースは、パーティショニングソリューションが混在しています。パーティション化されるのは「テーブル」(またはより一般的には「コレクション」)である場合があります。それ以外の場合は、「行」(または「ドキュメント」)です。HBaseのような列指向データベースのように、実際にはである場合もあります。使用しているテクノロジーに完全に依存します。これらすべてに共通することの1つは、エンジン自体がすべてを追跡することです。そのため、ドキュメントまたは行を要求するだけです。

もちろん、単に多数の異なるデータベースを作成するのではなく、実際にシャーディング機能を使用していると仮定しています。後者を行っている場合、あなたは自分でしています。

アプリケーションコードは、1つ以上のデータベースが複数のサーバーに分散していることを知る必要がありますか?そうでない場合、要求はどのレベルでフィルタリングされますか?

それらが異なる論理データベースである場合、はい。それらが物理的にのみ分散されている場合は、特定のデータベースがネイティブにシャーディングをサポートするか、負荷分散ソリューション(SQLデータベース用)を使用することを前提としています。また、すべての操作がステートレスであると仮定します。水平スケーリングが必要な場合は、ACIDを放棄する必要があります。

1データベース/ 1サーバーのセットアップを超える時期はいつですか?これを行う必要があるのはどれくらい一般的ですか?

1つのサーバーで可能な限りすべてを最適化しても、I / O負荷の制約のために十分なパフォーマンスを引き出すことができないときです。質問をしなければならない場合、それは早すぎます。

適切なRDBMS製品(Oracle、SQL Server)のパフォーマンスの問題は、設計、インデックス作成、クエリ、ロック競合などが原因で頻繁に発生することに注意してください。これらの製品は、とんでもない程度に垂直に拡張できます。繰り返しますが、パフォーマンスの問題がハードウェアの制限によるものであり、単に標準以下の設計/実装によるものではないことが確実な場合は、「1データベース/ 1サーバーのセットアップを超える」ことを検討してください。

または、分散データベースに切り替える人がいるもう1つの理由は、ライセンス料に多額の(または任意の)お金を支払う準備ができておらず、アプリケーションの複雑さを増すために低コストと引き換えにSQLを意識的な選択肢として捨てたいと思っていることです。あなたがソフトウェアのスタートアップであるが、通常は企業セクターには該当しない場合、まったく妥当な理由。


+1-私は実際にNoSQLを検討していませんでしたが、これはすべて同じように役立ちます。ありがとう。
VirtuosiMedia

1

データベースのレプリケーション構成には、主に3つのタイプがあります。

  • マスタースレーブ
  • マスターマスター
  • コンセンサス

マスタースレーブの例:MySQLマスター+ MySQLスレーブ、MongoDB

マスター-マスターの例:CouchDB、Cassandra、Riak

コンセンサスの例:ScalienDB

...いくつか例を挙げます。

これらには異なる特性があります。マスタースレーブ設定により、スレーブノードは最大速度でマスターに追いつくことができ、読み取り要求を非常に迅速に処理し、マスターサーバーがデータの整合性を管理します。すべての書き込みはマスターに送られるため、単一の比較的遅いライターが多くのリーダーをブロックしているため、ロックの競合はありませんが、一方で、スレーブサーバーは最終的に一貫性があり、トランザクション分離の保証は得られませんマスターからの読み取りのみ。(さらに読む; ACID vs BASE、トランザクション分離レベル、データベース複製、MVCC /分離:スナップショット、トランザクション複製)

マスター-マスターは常に書き込みを許可するので、本当のことについて複数の権限を持つことになります。これは問題になる場合もあれば、そうでない場合もありますが、アプリケーションの実行内容によって異なりますが、競合するデータを書き込むと、次にアプリケーションロジックとマージする必要があるキー/行/列を読み取ったときに複数の結果が得られる可能性がありますデータベースに保存します。(さらに読む:CAP定理、CouchDBレプリケーション、Riakレプリケーション、一貫性のあるハッシュ、BitcaskとStormDB、Quorum-ネットワーク分割のMongoDB、マージ解決戦略)

Scalienなどのノード間でレプリケーションを行うコンセンサスベースのデータベースは、常に書き込みで一貫していますが、書き込みを確認する前に複数のメッセージを交換します。これは、高速イーサネットがあり、ACKする前にディスクに書き込む必要がない場合、それほど問題ではありません。少なくとも3台のサーバーが別々の電源(1つ死に、他の2つはディスクに保存されていることを確認します)。(さらに読む:PAXOS、PAXOS COMMIT、分散トランザクションを使用した2フェーズコミット、3フェーズコミット)

その他の参考資料:(book: 'Elements of Distributed Computing'、ベクトルクロック、バージョンベクトル、マトリックスベクトル、論理クロック、ベーカリーアルゴリズム、インターバルツリークロック、アクターおよびリアクティブプログラミングおよびリアクター、ソフトウェアトランザクションメモリ、トランザクター、AKKA、Stact、分散コンピューティングの誤、ゴシッププロトコル、Cassandraのアンチエントロピーゴシッププロトコル拡張、分散ハッシュテーブル、分散設定でのデータのマージに関するペーパー、ZooKeeperアーキテクチャ、「非同期プロトコル」に関するInfoQプレゼンテーション、HBaseアーキテクチャ、MapReduceペーパー、Amazon DynamoペーパーすべてのNoSQLスタッフ、キューイング、rabbitmq高可用性クラスタリングを開始しました)

考えてみてください。この件に関するツイートも必要な場合は、Twitter @henrikfeldtで私をフォローできます。


1

それでは、スケーラビリティに関する別の視点を示します。

物事がデータであるということの意味、振る舞うことの意味、アプリケーションロジックを持つことの意味について説明しましょう。

通常、エンタープライズアプリケーションなどの土地に足を踏み入れると、階層化のアイデアに触れることになります。もちろん、ネットワークスタック(ISOモデル)、グラフィックス(Photoshop)、またはSOA(サービスは兄弟や子を呼び出すことはできますが、親を呼び出すことはできません)など、コンピューター内のあらゆる場所で階層化が行われます。

ただし、これまでに関係なく悪用されてきた特定のタイプのレイヤーは、「GUI」、「ビジネスロジックレイヤー」、「データアクセスレイヤー」です。共産主義は原則としては良いのですが、実際にはそうではありません。

理由を見てみましょう。使用する引数は、カップリングに関するものです。別のレイヤーのポイントに接触する1つのレイヤーのポイント。人々が入るdefault-enterprisey-modeでn層別名レイヤードアプリの作成を開始すると、レイヤー間で非常に多くの接点が作成されます。

基本的には、レイヤーは交換可能であるという考え方です。しかし、そうではありません!どうして?すべての呼び出しサイトのカップリングのため。

代わりに、ネットワークが切り離されている理由をご覧ください!インターフェースは、開いているソケットを指す単一のファイルポインター上のバイトストリームだからです!ISOモデルのすべてのレイヤーは、オブジェクト指向に対する「責任の連鎖」と呼ばれる設計パターンのようなものです!各層は、その下層のデータのセマンティクスを知らずに、下層をラップします。

データのパッケージは、下部のイーサネットおよび生の電気信号に向かって進むと、独自の特定のメッセージエンベロープ、送信可能な独自の「バイトバッチ」のみを知っているレイヤーによって継続的にラップされます。何もありません。パッケージの内容に応じて呼び出しパスを変更する必要はありません。

これとは対照的に、データベースに向かう途中でレイヤーを横断する「呼び出し」でアプリケーション層の呼び出しパスを変更する必要があるn層とは対照的です-たとえば、「ゴールドの顧客」は多態的に「通常の顧客」のスーパーセットですしたがって、「サブクラスごとのテーブル」を使用するため、データ(エンティティ)がレイヤーをトラバースしていることを知る必要があります。いわゆる「ビジネスロジックレイヤー」と、実際に保存を行っているデータレイヤーの両方で。

コンピューティングの観点からは、スケーラブルでも最適でもありません。

なぜスケーラブルでないのですか?アーキテクチャが結合されているため、多くのノードにスケールアウトしようとしているのと同じ古いDB内にいるためです!ただし、これにはACIDが必要であるため、その3つ目のエンティティ(データオブジェクト)は、トランザクションを行う単一のデータベースにそれらを保持する必要があります。

そうです、その暴言は邪魔になりません。他にどのような方法がありますか?

さて、「SOA」、つまりサービス指向アーキテクチャと呼ばれる嫌いな頭字語があります。もちろん、Tomas Erls of the worldでは、XMLとSOAPを代わりに使用してすべてのレイヤーを実装する必要があります。

上記のすべての理由から、これは間違った方法です。なぜなら、上記で説明したようにアプリケーション層に結合するのと同じように、XMLプロキシに結合するからです。

代わりに、メッセージングを使用し、それらに機能を実装するものは何でも聞かせてください。サービスサーフェスは、送信できるメッセージのリストになりますが、操作をサービスファサードに結合していません。また、これらの操作を実装しているアプリケーションやエンドポイントを知る必要さえありません。他のルーティングメカニズムが正しいコンシューマにルーティングするというメッセージを公開するだけですから!

実行する実際の操作からサービスファサードを切り離したため、複数のサービスを追加できるようになりました。実際、これがNetflixのやり方です。:これらのプレゼンテーションを見ていhttp://www.slideshare.net/adrianco/global-netflix-platformをhttp://www.slideshare.net/adrianco/global-netflix-platform。彼らは良いです!


0

ある新しいSQL(ACID)データベース弾性スケーリング特性を有することが主張されているベータ版では。現在進行中の無料のベータプログラムがあります。NuoDBと呼ばれる外観をお勧めします。

どうやら、シングルスレッドマシン上でもMySQLを容易に上回る性能を発揮しますが、特定のベンチマークでは70を超えるインスタンスまで喜んで拡張します。


シングルスレッド?それでは、関連するベンチマークはどうですか?
ヘンリック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.