2 つのまったく同じ構造のライブ データベースから取得したデータを含む読み取り専用データベースをすばやく実装する必要があります。
ライブ データベースは、実際には Dynamics 会計システムの企業データベースであるため、Dynamics 固有のアドバイスがあれば幸いですが、これは主に SQL に関する質問です。Great Plains が Microsoft に買収される前のかなり古いバージョンの Dynamics です。これは SQL Server 2000 上にあります。
Dynamics データにアクセスするレポートとアプリケーションがあります。これらのアプリは、1 つの会社のデータベースを参照するように設計されています。次に、別のものを追加する必要があります。これらのレポートとアプリのほとんどが結合されたデータを表示することは適切です。注文や請求書がどの会社に存在するかはあまり気にしません。少数のテーブルだけを見ます。
最も簡単な解決策は、結合されたデータを含むレポートのみのデータベースを作成することです。できれば、このデータベースを 1 日に数回変更して効率的に更新する方法が必要です。
私は開発者であり、データベースの専門家ではありませんが、私の計画は次のとおりです。
最初にライブ データベースと同じテーブル構造を持つ、必要なテーブルを含む結合レポート データベースを作成します。
すべての Dynamics テーブルには、DEX_ROW_ID と呼ばれる int ID 列があるようです。何に使用されるのかはわかりませんが(インデックスは作成されていません)、行を一意に識別するための明らかな一般的な方法のようです。レポート データベースでは、通常の int (ID ではありません) に変更します。すべてのデータベースの DEX_ROW_ID に一意のインデックスを作成します。
Dynamics にはタイムスタンプがないため、タイムスタンプ列をライブ データベースのテーブルに追加し、対応するバイナリ (8) 列をレポート データベースに追加します。私は、Dynamics が追加のインデックスと列によって動揺しないことを想定し、望んでいます。
int CompanyId 列をレポート データベース テーブルに追加し、一意のインデックスの末尾に追加します。それがなくても、ほとんどのデータは自然に一意になります。つまり、注文番号や請求書番号などは、2 つのライブ データベースで異なります。アプリケーションに若干の変更を加える必要があるかもしれませんが、新しいレポート データベースを指定する以外に多くのことを行う予定はありません。
レポート データベースが Reports と呼ばれ、ライブ データベースが Live1 と Live2 で、タイムスタンプ列が TS で、すべてのデータベースが同じサーバー上にあると仮定すると、MyTable と呼ばれる 1 つのテーブルの変更をコピーするための更新スクリプトを初めて試みます。 Live1 でレポート データベースに送信します。
USE Reports
CREATE TABLE #Changes
(
ReportId int,
LiveId int
)
/* Collect in a temp table the ids or rows which have been deleted or changed
in the live db L.DEX_ROW_ID will be null if the row has been deleted */
INSERT INTO #Changes
SELECT R.DEX_ROW_ID, L.DEX_ROW_ID
FROM MyTable R LEFT OUTER JOIN Live1.dbo.MyTable L ON L.DEX_ROW_ID = R.DEX_ROW_ID
WHERE R.CompanyId = 1 AND L.DEX_ROW_ID IS NULL OR L.TS <> R.TS
/* Delete rows that have been deleted or changed on the live db
I wonder if using join syntax would run better than the subquery. */
DELETE FROM MyTable
WHERE CompanyId = 1 AND DEX_ROW_ID IN (SELECT ReportId FROM #Changes)
/* Recopy rows that have changed in the live db */
INSERT INTO MyTable
SELECT 1 AS CompanyId, * FROM Live1.dbo.MyTable L
WHERE L.DEX_ROW_ID IN (SELECT ReportId FROM #Changes WHERE LiveId IS NOT NULL)
/* Copy the rows that are new in the live db */
INSERT INTO MyTable
SELECT 1 AS CompanyId, * FROM Live1.dbo.MyTable
WHERE DEX_ROW_ID > (SELECT MAX(DEX_ROW_ID) FROM MyTable WHERE CompanyId = 1)
次に、Live2 db についても同じことを行います。レポートのすべてのテーブルに対して繰り返します。リテラルの代わりにパラメーター @CompanyId を使用する必要があることはわかっていますが、C# プログラムなどでこれらを動的に生成する可能性のあるライブ データベース名に対してはそれを行うことができません。
ここで行っていることについて、アドバイス、提案、または批評を探しています。私はそれがアトミックではないことを知っています。このスクリプトの実行中に、ライブ データベースで何かが発生する可能性があります。私たちはそれと一緒に暮らすことができると思います。稼働中のデータベースで何も起きていないときは、おそらく毎晩または毎週のいずれかで完全なコピーを作成します。
エレガンスや完璧さよりもパフォーマンスを優先する必要があります。一部の初期テストでは、最大のテーブルに対して約 30 秒で実行される TS 比較の最初のクエリが含まれているため、これが機能することを楽観視していますが、明らかな何かが欠けているかどうか、または表示されていないかどうかも知りたいです。木のための森。
レポート データベースのログ ファイルを扱いたくありません。これを単純な復旧モデルに設定して、ログを忘れることはできますか?
ありがとう