4

パフォーマンスの考慮事項:行を複数のテーブルに分散するのではなく、すべての行を1つのテーブルに集中させます。

やあ。

アプリケーションで実行されるすべてのステップに関する情報をSQLDBに記録する必要があります。特定のテーブルがあります。ログを次のように関連付ける必要があります。製品-製品が作成されたときにログに記録する必要があります。注文-上記と同じ配送-同じなど。

データは頻繁に取得する必要があります。

私はそれを行う方法についていくつかのアイデアを持っています:

  1. これらすべてのテーブルの列を含むログテーブルを用意し、特定の製品のUIでデータを表現する場合は、Logから*を選択します。ここでLogId=Product.ProductIdです。たくさんの列があると面白いかもしれませんが、パフォーマンスが良くなると感じています。一方、このテーブルには大量の行があります。
  2. ログタイプ(ProductLogs、OrderLogsなど)ごとに多くのログテーブルがあるこのアイデアは一貫性がなく、同じ構造のテーブルがたくさんあるので意味がないので、私は本当に好きではありませんが、(?)検索する方が速いかもしれません行数が少ないテーブルで(間違っていますか?)。
  3. ステートメント番号によると。1、LogId、TableNameId、およびRowId列を持ち、データを取得するためのUDF(log id 234など)よりも、ログ行をDB内の多くのテーブル行に参照する2番目の多対1テーブルを作成できます。 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
4

4 に答える 4

3

データベースの事前最適化には注意してください。ほとんどのデータベースは適度に高速で、やや複雑です。最初に効率のテストを実行します。

次に、すべてを1つのテーブルに配置すると、必要な結果がキャッシュにある可能性が高くなり、パフォーマンスが大幅に向上します。残念ながら、それはまた、あなたが探しているものを見つけるために巨大なテーブルを検索しなければならない可能性がはるかに高くなります。これはインデックスで部分的に解決できますが、インデックスは無料ではありません(たとえば、書き込みがより高価になります)。

私のアドバイスは、パフォーマンスが本当に重要かどうかをテストしてから、さまざまなシナリオをテストして、どれが最速かを確認することです。

于 2009-07-17T09:43:27.430 に答える
2

大量のデータ(数百万行以上)について話している場合は、さまざまなテーブルを使用してそれらを格納することでメリットが得られます。

たとえば、5つの異なる「タイプ」のログテーブルを想定した基本的な例5,000万のログエントリ1x5,000万の行テーブルよりも5x1,000万の行テーブルがある方がよい

  • INSERTのパフォーマンスは、個々のテーブルで向上します。各テーブルのインデックスは小さくなり、挿入操作の一部として更新/保守するのがより迅速/簡単になります。

  • READのパフォーマンスは、個々のテーブルで向上します。クエリするデータが少なくなり、トラバースするインデックスが小さくなります。また、レコードがどのタイプのログエントリであるかを識別するために、追加の列を保存する必要があるようです(Product、Shipping ....)

  • 小さなテーブルのメンテナンスはそれほど苦痛ではありません(統計、インデックスのデフラグ/再構築など)

基本的に、これはデータのパーティション化に関するものです。SQL 2005以降、パーティショニングのサポートが組み込まれています(ここを参照)が、そのためにはEnterprise Editionが必要です。これにより、基本的に1つのテーブルにデータをパーティショニングしてパフォーマンスを向上させることができます(たとえば、1つのログテーブルを作成してからその中のデータがどのように分割されるかを定義します)

最近、eBayアーキテクトの1人とのインタビューを聞きました。彼は、パフォーマンスとスケーラビリティが必要な場合にパーティション化の重要性を強調し、私の経験に基づいて強く同意します。

于 2009-07-17T09:53:58.203 に答える
1

いくつかの理由から、私は間違いなくオプション3を選択します。

データは、テーブル名(オプション2)またはフィールド名(オプション1)としてではなく、テーブルのフィールドにある必要があります。そうすることで、データベースの操作と保守が容易になります。

一般的に、テーブルが狭いほどパフォーマンスが向上します。行数は、フィールド数よりもパフォーマンスへの影響が少なくなります。

各テーブルにフィールドがある場合(オプション1)、操作の影響を受けるテーブルが少ないと、多くの空のフィールドが表示される可能性があります。

于 2009-07-17T10:18:12.493 に答える
0

必要に応じてデータベースモデルを1つから別のデータベースモデルに変更できるように、データアクセス層を実装してみてください。そうすれば、1つを選択するだけで、後でパフォーマンスへの影響を心配できます。

パフォーマンステストを実行せず、負荷の種類を正確に把握しないと、パフォーマンスは読み取り数、書き込み数、書き込み数などの多くの要因に依存するため、最適化が困難になります。読み取りと書き込みが競合してロックを引き起こす可能性があります。

私の好みはオプション1です。これは最も簡単な方法であり、さまざまな種類の問題を修正するために実行できる調整がいくつかあります。

于 2009-07-17T09:49:15.670 に答える