considération de performance: Étendre les lignes dans plusieurs tables vs concentrer toutes les lignes dans une table

StackOverflow https://stackoverflow.com/questions/1142296

Question

considération de performance:. Lignes de répandirent dans plusieurs tables vs concentré toutes les lignes dans une table

Salut.

Je dois enregistrer des informations sur au sujet de toutes les étapes qui se passe dans l'application dans une base de données SQL. Il y a certaines tables, je veux doit être le journal lié à: Produit - doit se connecter lorsqu'un produit a été créé changé, etc. Ordre - comme ci-dessus Expédition - même etc etc etc.

Les données seront récupérées doivent être souvent.

J'ai quelques idées sur la façon de le faire:

  1. Avoir une table de journal qui contiendra des colonnes pour toutes ces tables, quand je veux représenter des données dans l'interface utilisateur pour un certain produit fera select * from Log où LogId = Produit.IDProduit. Je sais que cela pourrait être drôle d'avoir beaucoup Col., mais j'ai ce sentiment que la performance sera meilleure. D'un autre côté, il y aura une énorme quantité de lignes dans ce tableau.
  2. Demandez à de nombreuses tables de journaux pour chaque type de journal (ProductLogs, OrderLogs etc.) Je n'aime vraiment pas cette idée car il n'est pas cohérente et ont de nombreuses tables avec une même structure n'a pas de sens, mais (?), Il est peut-être plus rapide lors de la recherche d'une table qui a une quantité inférieure de lignes (mi mal?).
  3. Selon la déclaration n °. 1, je pourrais faire un second nombre à une table qui aura Col. LogId, TableNameId et rowid et fera référence à une ligne de journal à plusieurs lignes de la table dans la base de données, que aura une UDF pour récupérer des données (par exemple log id 234 appartient à la clientèle au tableau CustomerId 345 et à la table du produit où productId = RowId); Je pense que c'est la plus belle façon de le faire, mais encore une fois, il pourrait y avoir une énorme quantité de lignes, va ralentir la recherche? ou voilà comment cela doit être fait, whatcha dire? ...

Exemple n ° 3 dans la liste ci-dessus:

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
Était-ce utile?

La solution

Je serais certainement prêt pour l'option 3, pour plusieurs raisons:

Les données doivent être dans les champs d'une table, et non comme un nom de table (option 2) ou un nom de champ (option 1). De cette façon, la base de données devient plus facile de travailler avec et plus facile à entretenir.

tables genrally mieux effectuer plus étroites. Le nombre de lignes a moins d'impact sur les performances que le nombre de champs.

Si vous avez un champ pour chaque table (option 1), vous êtes susceptible d'obtenir beaucoup de champs vides quand seulement quelques-unes des tables sont affectées par une opération.

Autres conseils

Soyez prudent avec les bases de données preoptimizing. La plupart des bases de données sont assez rapide et peu compliquée. Vous souhaitez exécuter un test d'efficacité d'abord.

Deuxième tout mettre dans une table, il est plus probable que les résultats que vous voulez sont dans le cache qui accélère grandement les performances. Malheureusement, il fait aussi beaucoup plus probable que vous devrez rechercher une table gigantesque pour trouver ce que vous recherchez. Cela peut être en partie résolu avec un index, mais les indices ne sont pas gratuits (ils font écrire plus cher, pour un).

Mon conseil serait de faire un test pour voir si les performances vraiment d'importance et tester les différents scénarios pour voir qui est le plus rapide.

Si vous parlez de grands volumes de données (en millions de lignes +), alors vous aurez un avantage d'utiliser des tableaux différents pour les stocker dans.

par exemple. exemple de base de 50 millions d'entrées du journal, en supposant 5 différents « types » de table de journal Il vaut mieux avoir 5 x 10 M tables de rangée à 1 x 50 M table de rangée

  • La performance INSERT sera meilleure avec des tables individuelles - index sur chaque table seront plus petits et donc plus rapide / plus facile à être mis à jour / maintenue dans le cadre de l'opération d'insertion

  • performances de lecture sera mieux avec des tables individuelles - moins de données à la requête, les index plus petits à parcourir. En outre, des sons comme vous auriez besoin de stocker une colonne supplémentaire pour identifier quel type d'entrée du journal d'un dossier est (produit, livraison ....)

  • MAINTENANCE sur les tables plus petites est moins douloureux (statistiques, l'indice defragging / reconstruction, etc.)

Il s'agit essentiellement sur les données de partitionnement. A partir de SQL de 2005, il a un support intégré pour le partitionnement (voir ) mais vous avez besoin Enterprise Edition pour cela, ce qui vous permet essentiellement de partitionner les données dans une table pour améliorer les performances (par exemple, vous auriez votre une table de journal, puis définir la façon dont les données qu'il est partitionné)

J'ai écouté une entrevue avec l'un des architectes eBay récemment, qui a souligné l'importance du partage lorsqu'ils ont besoin performances et l'évolutivité et je suis d'accord fortement basé sur mes expériences.

Essayez de mettre en œuvre votre couche d'accès aux données d'une manière afin que vous puissiez passer d'un modèle de base de données à un autre en cas de besoin -. De cette façon vous suffit de choisir l'un et l'inquiétude au sujet des implications de performance plus tard

Sans faire des tests de performance et d'avoir une idée précise des sortes de charger vous allez obtenir ça va être difficile d'optimiser que la performance dépend d'un certain nombre de facteurs, tels que le nombre de lectures, le nombre d'écritures et si le lit ou non, et les écritures sont susceptibles de blocage des conflits et la cause.

Ma préférence serait pour l'option 1 BTW -. Le plus simple à faire et il y a un certain nombre de réglages que vous pouvez faire pour aider fix différentes sortes de problèmes que vous pourriez avoir

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top