Domanda

Dovremmo usare un flag per eliminazioni morbide o una tabella di falegnameria separata? Quale è più efficiente? Il database è SQL Server.

Informazioni di base

Qualche tempo fa abbiamo fatto entrare un consulente DB e guardare il nostro schema di database. Quando eliminiamo un record, aggiorneremmo un flag isdelettato sulle tabelle appropriate. È stato suggerito che invece di usare una bandiera, memorizzare i record eliminati in una tabella separata e utilizzare un join in quanto sarebbe meglio. Ho messo questo suggerimento al test, ma almeno in superficie, il tavolo extra e il join sembrano essere più costosi di quanto usare una bandiera.

Test iniziali

Ho impostato questo test.

Due tabelle, esempio e esemplare eliminato. Ho aggiunto un indice non cluster sulla colonna ISDLET.

Ho fatto tre test, caricando un milione di record con i seguenti rapporti eliminati/non eliminati:

  • Cancellato/non sieduto
  • 50/50
  • 10/90
  • 1/99

Risultati - 50/5050 50

Risultati - 10/9010 90

Risultati - 1/99enter image description here

Script di database, per riferimento, esempio, esemplare eliminato e indice per esempio.

CREATE TABLE [dbo].[Example](
    [ID] [int] NOT NULL,
    [Column1] [nvarchar](50) NULL,
    [IsDeleted] [bit] NOT NULL,
 CONSTRAINT [PK_Example] PRIMARY KEY CLUSTERED 
(
    [ID] 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].[Example] ADD  CONSTRAINT [DF_Example_IsDeleted]  DEFAULT ((0)) FOR [IsDeleted]
GO

CREATE TABLE [dbo].[DeletedExample](
    [ID] [int] NOT NULL,
 CONSTRAINT [PK_DeletedExample] PRIMARY KEY CLUSTERED 
(
    [ID] 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].[DeletedExample]  WITH CHECK ADD  CONSTRAINT [FK_DeletedExample_Example] FOREIGN KEY([ID])
REFERENCES [dbo].[Example] ([ID])
GO

ALTER TABLE [dbo].[DeletedExample] CHECK CONSTRAINT [FK_DeletedExample_Example]
GO

CREATE NONCLUSTERED INDEX [IX_IsDeleted] ON [dbo].[Example] 
(
    [IsDeleted] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
È stato utile?

Soluzione

I numeri che hai sembra indicarlo la mia impressione iniziale era corretto: se la tua query più comune rispetto a questo database è filtrare IsDeleted = 0, quindi le prestazioni saranno migliori con una semplice flag di bit, soprattutto se si fa un uso saggio degli indici.

Se si interrogano spesso per i dati eliminati e non slittati separatamente, è possibile vedere un guadagno di prestazioni avendo una tabella per oggetti eliminati e un altro per gli elementi non slittati, con campi identici. Ma denormalizzare i tuoi dati in questo modo è raramente una buona idea, poiché il più spesso ti costerà molto più nei costi di manutenzione del codice di quanto non ti guadagnerà negli aumenti delle prestazioni.

Altri suggerimenti

Non sono l'esperto SQL, ma secondo me, tutto dipende dalla frequenza di utilizzo del database. Se il database è accessibile dall'ampio numero di utenti e deve essere efficiente, l'utilizzo di una tabella ispelata separata sarà buono. L'opzione migliore sarebbe l'utilizzo di una bandiera durante il tempo di produzione e come parte di Maintanace giornaliera/settimanale/mensile è possibile spostare tutti i record eliminati morbidi sulla tabella isdelata e cancellare la tabella di produzione dei record eliminati morbidi. La miscela di entrambe le opzioni sarà buona.

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