2009-08-12 21 views
1

Ich muss Daten in einer SQL Server 2008-Datenbank aus verschiedenen Datenquellen mit unterschiedlichen Datentypen speichern. Folgende Datentypen sind zulässig: Bit, Numerisch (1, 2 oder 4 Byte), Real und String. Es wird einen Wert, einen Zeitstempel, einen FK für den Gegenstand, zu dem der Wert gehört, und einige andere Informationen für die gespeicherten Daten geben.SQL-Design für verschiedene Datentypen

Die wichtigsten Punkte sind die Leseleistung und die Größe der Daten. Es kann ein paar tausend Gegenstände geben und jeder Gegenstand kann Millionen von Werten haben.

Ich habe 5 möglichen Optionen:

  1. Getrennte Tabellen für jeden Datentyp (ValueBit, ValueTinyInt, ValueSmallInt, etc ... Tabellen)
  2. Separate Tabellen mit Vererbung (Wertetabelle als Basistabelle, ValueBit Tabelle nur zum Speichern des Bitwertes, etc ...)
  3. Einzelwerttabelle für alle Datentypen, mit separaten Feldern für jeden Datentyp (Werttabelle, mit ValueBit BIT, ValueTinyInt TINYINT etc ...)
  4. Single Tabelle und Einzelwertfeld mit sql_variant
  5. Einzeltisch und Einzelwertfeld UDT mit

Mit Fall 2 ist ein PK ein Muss, und,

1000 item * 10 000 000 data each > Int32.Max, and, 
1000 item * 10 000 000 data each * 8 byte BigInt PK is huge 

Other than that, ich bin die Prüfung 1 oder 3 ohne PK. Werden sie sich in der Größe unterscheiden?

Ich habe keine Erfahrung mit 4 oder 5 und ich denke nicht, dass sie in diesem Szenario gut funktionieren werden.

Wohin soll ich gehen?

+0

Ich bin noch am messen. Bisher sind die Optionen 3 und 4 ähnlich: Sie sind ziemlich schnell und benötigen weniger Speicherplatz als 1 und 2. Geringere Spalten benötigen mehr Platz und sind langsamer. Bei abdeckenden Indizes ist die Leseleistung besser als erwartet. – Recep

Antwort

0

Was Nutzungsszenarien sind? Beginnen Sie mit Stichproben von Abfragen und berechnen Sie die erforderlichen Indizes. Betrachten Sie die Datenpartitionierung wie zuvor erwähnt. Versuchen Sie, Ihre Daten/Beziehungen besser zu verstehen. Ich glaube, dass die Entscheidung auf der geschäftlichen Bedeutung/Nutzung der Daten basieren sollte.

+0

Ich möchte das nicht unbeantwortet lassen. Was ich angewendet habe, entspricht deinem Vorschlag, also wähle ich deine Antwort. Option 3 war der richtige Weg. – Recep

1

Ihre Frage ist schwer zu beantworten, da Sie scheinbar ein relationales Datenbanksystem für etwas verwenden, für das es nicht vorgesehen ist. Die Daten, die Sie in der Datenbank behalten möchten, scheinen zu unstrukturiert zu sein, um von einem relationalen Datenbanksystem viel Nutzen zu ziehen. Datenbankdesigns mit meist Feldern wie "Parametertyp" und "Parameterwert", die versuchen, sehr generische Situationen abzudecken, werden meist als schlechte Designs angesehen. Vielleicht sollten Sie eine "nicht relationale Datenbank" wie BigTable verwenden. Wenn Sie wirklich ein relationales Datenbanksystem verwenden möchten, empfehle ich dringend, Anfang der Datenbank-Design von Clare Churcher zu lesen. Es ist leicht zu lesen, bringt Sie aber in Bezug auf RDBS auf den richtigen Weg.

0

Ich denke, es ist eine gute Frage - Diese Situation ist ziemlich häufig, obwohl es schwierig ist, Tabellen zu machen, um es zu unterstützen.

In Bezug auf die Leistung verschwendet eine Tabelle wie in # 3 angegeben möglicherweise eine große Menge an Speicher und RAM, da Sie für jede Zeile Speicherplatz für einen Wert von jedem Typ zuweisen, aber nur einen verwenden. Wenn Sie das neue Sparse-Tabellen-Feature von 2008 verwenden, könnte es hilfreich sein, aber es gibt noch andere Probleme: Es ist ein wenig schwierig zu beschränken/normalisieren, weil nur einer der mehreren Werte für jede Zeile gefüllt werden soll - mit zwei Werten in zwei Spalten wäre ein Fehler, aber das Design spiegelt das nicht wider. Ich würde das durchkreuzen. Wenn ich das wäre, würde ich nach Option 1 oder 2 oder 4 suchen, und die Entscheidung würde davon ausgehen: Muss ich normalerweise eine Abfrage erstellen, die Zeilen zurückgibt, die einen Mix von Werten haben von verschiedenen Typen in der gleichen Ergebnismenge?Oder werde ich fast immer nach den Zeilen nach Artikel und nach Typ fragen. Ich frage, denn wenn die Werte verschiedene Typen sind, bedeutet das für mich einen Unterschied in der Quelle oder der Verwendung dieser Daten (es ist zum Beispiel unwahrscheinlich, dass Sie eine Zeichenkette und eine reale Zeichenkette oder eine Zeichenkette und ein Bit miteinander vergleichen) Dies ist wichtig, da unterschiedliche Tabellen pro Typ möglicherweise einen erheblichen Leistungs-/Skalierbarkeitsvorteil darstellen, wenn die Daten auf diese Weise schneller verarbeitet werden. Das Partitionieren von Daten in kleinere Sätze enger verwandter Daten kann einen Leistungsvorteil ergeben.

Es ist so, als hätten wir alle Daten in einem großen (wenn auch sortierten) Satz oder in kleinere, zusammengehörige Mengen unterteilt. Die kleineren Sätze bevorzugen einige Arten von Abfragen, und wenn dies die Abfragen sind, die Sie benötigen, ist es ein Gewinn.

Details:

CREATE TABLE [dbo].[items](
    [itemid] [int] IDENTITY(1,1) NOT NULL, 
    [item] [varchar](100) NOT NULL, 
CONSTRAINT [PK_items] PRIMARY KEY CLUSTERED 
(
    [itemid] ASC 
) 
) 

/* This table has the problem of allowing two values 
in the same row, plus allocates but does not use a 
lot of space in memory and on disk (bad): */ 

CREATE TABLE [dbo].[vals](
    [itemid] [int] NOT NULL, 
    [datestamp] [datetime] NOT NULL, 
    [valueBit] [bit] NULL, 
    [valueNumericA] [numeric](2, 0) NULL, 
    [valueNumericB] [numeric](8, 2) NULL, 
    [valueReal] [real] NULL, 
    [valueString] [varchar](100) NULL, 
CONSTRAINT [PK_vals] PRIMARY KEY CLUSTERED 
(
    [itemid] ASC, 
    [datestamp] ASC 
) 
) 

ALTER TABLE [dbo].[vals] WITH CHECK 
ADD CONSTRAINT [FK_vals_items] FOREIGN KEY([itemid]) 
REFERENCES [dbo].[items] ([itemid]) 
GO 

ALTER TABLE [dbo].[vals] CHECK CONSTRAINT [FK_vals_items] 
GO 


/* This is probably better, though casting is required 
all the time. If you search with the variant as criteria, 
that could get dicey as you have to be careful with types, 
casting and indexing. Also everything is "mixed" in one 
giant set */ 

CREATE TABLE [dbo].[allvals](
    [itemid] [int] NOT NULL, 
    [datestamp] [datetime] NOT NULL, 
    [value] [sql_variant] NOT NULL 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[allvals] WITH CHECK 
ADD CONSTRAINT [FK_allvals_items] FOREIGN KEY([itemid]) 
REFERENCES [dbo].[items] ([itemid]) 
GO 

ALTER TABLE [dbo].[allvals] CHECK CONSTRAINT [FK_allvals_items] 
GO 


/* This would be an alternative, but you trade multiple 
queries and joins for the casting issue. OTOH the implied 
partitioning might be an advantage */ 

CREATE TABLE [dbo].[valsBits](
    [itemid] [int] NOT NULL, 
    [datestamp] [datetime] NOT NULL, 
    [val] [bit] NOT NULL 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[valsBits] WITH CHECK 
ADD CONSTRAINT [FK_valsBits_items] FOREIGN KEY([itemid]) 
REFERENCES [dbo].[items] ([itemid]) 
GO 

ALTER TABLE [dbo].[valsBits] CHECK CONSTRAINT [FK_valsBits_items] 
GO 

CREATE TABLE [dbo].[valsNumericA](
    [itemid] [int] NOT NULL, 
    [datestamp] [datetime] NOT NULL, 
    [val] numeric(2, 0) NOT NULL 
) ON [PRIMARY] 

GO 

... FK constraint ... 

CREATE TABLE [dbo].[valsNumericB](
    [itemid] [int] NOT NULL, 
    [datestamp] [datetime] NOT NULL, 
    [val] numeric (8, 2) NOT NULL 
) ON [PRIMARY] 

GO 

... FK constraint ... 

etc... 
+0

Vielen Dank für die Erinnerung an die spärlichen Spalten, kann es in dieser Situation nützlich sein. Ihre Antwort ist sehr hilfreich, ich bewerte auch Ihre anderen Punkte. – Recep

Verwandte Themen