Prestazioni considerazione: Stendere le righe in più tabelle vs concentrare tutte le righe in una tabella

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

Domanda

Performance considerazione:. Filari diffondersi in più tabelle vs concentrato tutte le righe in una tabella

Ciao.

Ho bisogno di registrare le informazioni su ogni passo che va avanti nell'applicazione in un DB SQL. Ci sono alcune tabelle, voglio che il registro dovrebbe essere correlato a: Prodotto - deve accedere quando un prodotto è stato creato cambiato ecc Order - come sopra Spedizione - stesso ecc ecc ecc.

sarà bisogno dei dati da recuperare spesso.

ho alcune idee su come farlo:

  1. Avere una tabella di log che conterrà le colonne per tutte queste tabelle, quindi quando voglio rappresentare i dati nell'interfaccia utente per un determinato prodotto farà select * from Log dove LOGID = Product.ProductId. So che questo potrebbe essere divertente avere molti colli, ma ho la sensazione che le prestazioni saranno migliori. In altra parte ci sarà una quantità enorme di righe in questa tabella.
  2. Avere tanti tavoli di registro per ogni tipo di registro (ProductLogs, OrderLogs etc.) Io davvero non piace questa idea in quanto non è coerente e hanno molti tavoli con stessa struttura non ha senso, ma (?) Potrebbe essere più veloce durante la ricerca in una tabella che ha un importo inferiore di righe (mi va?).
  3. Secondo la dichiarazione n. 1, ho potuto fare un secondo molti a una tabella che avrà LOGID, TableNameId e ROWID colli, e farà riferimento fila log per molte righe della tabella nel DB, che avrà un'UDF per recuperare i dati (ad esempio ID 234 log appartiene alla tabella clienti al CustomerId 345 e al tavolo del prodotto in cui productId = RowId); Credo che questo sia il modo più bello per farlo, ma ancora una volta, ci potrebbe essere una quantità enorme di righe, sarà rallentare la ricerca? o questo è come dovrebbe essere fatto, Whatcha Say? ...

Esempio n ° 3 nella lista sopra:

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
È stato utile?

Soluzione

avrei sicuramente andare per l'opzione 3, per diversi motivi:

I dati devono essere nei campi di una tabella, non come un nome di tabella (opzione 2) o di un nome di campo (opzione 1). In questo modo il database diventa più facile da lavorare e più facile da mantenere.

tavoli più strette genrally un rendimento migliore. Il numero di righe ha un impatto minore sulle prestazioni rispetto al numero di campi.

Se si dispone di un campo per ogni tabella (opzione 1), si rischia di ottenere un sacco di campi vuoti, quando solo alcuni dei tavoli sono affetti da un'operazione.

Altri suggerimenti

Fare attenzione con i database preoptimizing. La maggior parte delle basi di dati sono ragionevolmente veloce e un po 'complicato. Si desidera eseguire un test per l'efficienza prima.

In secondo luogo mettere tutto in una tabella rende più probabile che i risultati desiderati sono nella cache in grado di accelerare le prestazioni immensamente. Purtroppo rende anche molto più probabile che si dovrà cercare un tavolo enorme per trovare quello che stai cercando. Ciò può essere parzialmente risolto con un indice, ma gli indici non venire liberi (fanno crei più costoso, per uno).

Il mio consiglio sarebbe quello di fare un test per vedere se le prestazioni veramente importante e quindi verificare i diversi scenari per vedere quale è il più veloce.

Se si sta parlando di grandi volumi di dati (milioni di righe +), allora si otterrà un beneficio dall'uso di tabelle diverse per memorizzarli in.

es. esempio di base di 50 milioni di voci di registro, assumendo 5 diversi "tipi" di tabella del log Meglio avere 5 x 10 milioni di tavoli fila di 1 x 50 milioni tavolo fila

  • prestazioni INSERT sarà meglio con i singoli tavoli - Indici su ogni tavolo saranno più piccoli e quindi più veloce / più facile essere aggiornato / mantenuto come parte del l'operazione di inserimento

  • prestazioni LEGGI sarà migliore con i singoli tavoli - meno dati da interrogare, indici piccole per attraversare. Inoltre, suona come avresti bisogno di memorizzare una colonna in più per identificare il tipo di voce del registro è un record (del prodotto, il trasporto ....)

  • MANUTENZIONE a tavoli più piccoli è meno doloroso (statistiche, indice di deframmentazione / ricostruzione etc)

In sostanza, si tratta di dati di partizionamento. Da SQL 2005 in poi, ha un supporto incorporato per il partizionamento (vedi qui ) ma è necessario Enterprise Edition per questo, che permette in sostanza di partizionare i dati in una tabella per migliorare le prestazioni (ad esempio, si avrebbe la vostra una tabella Log, e quindi definire come i dati al suo interno è partizionato)

Ho ascoltato un'intervista con uno degli architetti di eBay di recente, che ha sottolineato l'importanza di partizionamento quando ha bisogno di prestazioni e scalabilità e sono d'accordo fortemente basato sulle mie esperienze.

Prova a implementare il livello di accesso ai dati in modo in modo da poter passare da un modello di database ad un altro, se necessario -. In questo modo si basta scegliere uno e preoccuparsi di implicazioni sulle prestazioni successive

Senza fare un po 'di test delle prestazioni e avere un'idea precisa dei tipi di caricare la vostra intenzione di ottenere la sua intenzione di essere difficile ottimizzare la prestazione dipende da una serie di fattori, quali il numero di letture, il numero di scritture e se il letture e le scritture sono suscettibili di conflitto e la causa di blocco.

La mia preferenza sarebbe per l'opzione 1 btw -. Nel caso più semplice da fare e ci sono una serie di modifiche si può fare per dare una mano fix vari tipi di problemi che potreste avere

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top