パフォーマンスに関する考慮事項:複数のテーブルに行を分散するのではなく、すべての行を 1 つのテーブルに集中させる
-
16-09-2019 - |
質問
パフォーマンスに関する考慮事項:複数のテーブルに行を分散するのではなく、すべての行を 1 つのテーブルに集中させます。
こんにちは。
アプリケーションで実行されるすべてのステップに関する情報を SQL DB に記録する必要があります。特定のテーブルがあり、ログを以下に関連付ける必要があります。製品 - 製品が作成されたとき、変更されたときなどにログを記録する必要があります。順序 - 上記と同じ 配送 - 同じ 等。等等
データは頻繁に取得する必要があります。
それを行う方法についてはいくつかのアイデアがあります:
- これらすべてのテーブルの列を含むログ テーブルがある場合、特定の製品の UI でデータを表現したい場合は、select * from Log where LogId = Product.ProductId を実行します。コルが多いと面白いかもしれないとは思いますが、パフォーマンスは向上するだろうと感じています。一方、このテーブルには膨大な量の行が存在します。
- 各ログ タイプ (ProductLogs、OrderLogs など) に多数のログ テーブルを用意する このアイデアは一貫性がなく、同じ構造のテーブルを多数持つのは意味がないので、あまり好きではありませんが、(?) 検索するときは速いかもしれません。行数が少ないテーブル内です (間違っていますか?)。
- ステートメント番号によると、1、LogId、TableNameId、RowId 列を持ち、ログ行を DB 内の多くのテーブル行に参照し、データを取得するための UDF を持つ 2 番目の多対 1 テーブルを作成できます (例:ログ ID 234 は、CustomerId 345 の Customer テーブルと、productId = RowId の Product テーブルに属します。これが最も良い方法だと思いますが、やはり膨大な量の行がある可能性があり、検索が遅くなりますか?それともこうするべきなのか、何と言いますか?...
いいえの例上記のリストの 3:
CREATE TABLE [dbo].[Log](
[LogId] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NULL,
[Description] [varchar](1024) NOT NULL,
CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED
(
[LogId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Log] WITH CHECK ADD CONSTRAINT [FK_Log_Table] FOREIGN KEY([UserId])
REFERENCES [dbo].[Table] ([TableId])
GO
ALTER TABLE [dbo].[Log] CHECK CONSTRAINT [FK_Log_Table]
---------------------------------------------------------------------
CREATE TABLE [dbo].[LogReference](
[LogId] [int] NOT NULL,
[TableName] [varchar](32) NOT NULL,
[RowId] [int] NOT NULL,
CONSTRAINT [PK_LogReference] PRIMARY KEY CLUSTERED
(
[LogId] ASC,
[TableName] ASC,
[RowId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[LogReference] WITH CHECK ADD CONSTRAINT [FK_LogReference_Log] FOREIGN KEY([LogId])
REFERENCES [dbo].[Log] ([LogId])
GO
ALTER TABLE [dbo].[LogReference] CHECK CONSTRAINT [FK_LogReference_Log]
---------------------------------------------------------------------
CREATE FUNCTION GetLog
(
@TableName varchar(32),
@RowId int
)
RETURNS
@Log TABLE
(
LogId int not null,
UserId int not null,
Description varchar(1024) not null
)
AS
BEGIN
INSERT INTO @Log
SELECT [Log].LogId, [Log].UserId, [Log].Description
FROM [Log] INNER JOIN
LogReference ON [Log].LogId = LogReference.LogId
WHERE (LogReference.TableName = @TableName) AND (LogReference.RowId = @RowId)
RETURN
END
GO
解決
私は間違いなく、いくつかの理由のために、オプション3のために行くだろう。
データがないテーブル名(オプション2)またはフィールド名(オプション1)のように、テーブルのフィールドであるべきです。その方法は、データベースを維持するためと連携し、より簡単にすることが容易になります。
狭いテーブルはgenrallyパフォーマンスが向上。行の数は、フィールドの数よりも性能にあまり影響を与えます。
あなたが各テーブル(オプション1)のためのフィールドを持っている場合は、テーブルのほんの数は、操作の影響を受けているとき、、あなたは空のフィールドの多くを取得する可能性があります。
他のヒント
preoptimizingデータベースには注意してください。ほとんどのデータベースには、合理的に速く、やや複雑です。あなたは最初の効率化のためのテストを実行したい。
は、2つ目のテーブルですべてを置くことは、あなたが望む結果は非常にパフォーマンスをスピードアップしますキャッシュ内にある可能性が高くなります。残念ながら、それはまた、より多くの可能性が高いあなたが探しているものを見つけるために巨大なテーブルを検索する必要があることになります。 (彼らは1のために、より高価な書き込みを作る)これは、部分的にインデックスを使用して解決することができますが、インデックスは無料付属していません。
私のアドバイスは、パフォーマンスは本当に問題、その後、最速であるかを確認するためにさまざまなシナリオをテストするかどうかを確認するためにテストを行うことであろう。
大量のデータ (数百万行以上) について話している場合、それらを保存するために別のテーブルを使用すると利点が得られます。
例えば基本的な例 5,000 万個のログ エントリ (5 つの異なる「タイプ」のログ テーブルを想定) 5,000万行のテーブルを1つ持つよりも、1,000万行のテーブルを5つ持つ方が良い
INSERT のパフォーマンスは、テーブルを個別に使用することで向上します。各テーブルのインデックスが小さくなるため、挿入操作の一部として更新/保守がより速く/簡単になります。
個々のテーブルを使用すると READ パフォーマンスが向上します。クエリするデータが減り、走査するインデックスが少なくなります。また、レコードのログエントリの種類 (製品、出荷など) を識別するために追加の列を保存する必要があるようです。
- 小さなテーブルのメンテナンスはそれほど苦痛ではありません (統計、インデックスのデフラグ/再構築など)。
基本的に、これはデータのパーティション分割に関するものです。SQL 2005 以降、パーティショニングのサポートが組み込まれています (「 ここ)ただし、それには Enterprise Edition が必要です。Enterprise Edition を使用すると、基本的にデータを 1 つのテーブルに分割してパフォーマンスを向上させることができます(例:ログ テーブルを 1 つ用意して、その中のデータをどのように分割するかを定義します)
最近、eBay アーキテクトの 1 人へのインタビューを聞きましたが、彼はパフォーマンスとスケーラビリティが必要な場合のパーティショニングの重要性を強調していました。私の経験に基づいて、私も強く同意します。
必要な場合は、別のデータベースモデルから変更できるような方法であなたのデータアクセス層を実装するようにしてください - あなただけのものを選択し、後でパフォーマンスへの影響を心配している方法
。いくつかのパフォーマンステストを行うと、あなたは、その性能は、このような読み込み回数、書き込み回数などの要因の数に依存して最適化することは困難になるだろうを取得するつもり負荷の種類の正確なアイデアを持たずに、読み取りと書き込みが競合し、原因ロックする可能性があります。かと
私の好みはところでオプション1のためになる - 。やって最も単純な、あなたが持っている可能性のある問題の修正各種を助けるために何ができるの調整の数があります。