Zde je model pro splnění vašeho stanoveného požadavku.
Odkaz na datový model časové řady
Odkaz na zápis IDEF1X pro ty, kteří neznají standard relačního modelování.
-
Normalizováno na 5NF; žádné duplicitní sloupce; žádné anomálie aktualizací, žádné nuly.
-
Když se stav produktu změní, stačí do ProductStatus vložit řádek s aktuálním datem a časem. Není třeba se dotýkat předchozích řádků (které byly pravdivé a zůstávají pravdivé). Žádné fiktivní hodnoty, které musí nástroje pro vytváření přehledů (jiné než vaše aplikace) interpretovat.
-
DateTime je skutečné datum a čas, kdy byl produkt umístěn do tohoto stavu; "Od", chcete-li. „Do“ lze snadno odvodit:je to Datum a čas dalšího řádku (DateTime> „Od“) pro Produkt; tam, kde neexistuje, je hodnotou aktuální datum a čas (použijte ISNULL).
První model je kompletní; (ProductId, DateTime) stačí k poskytnutí jedinečnosti pro primární klíč. Protože však požadujete rychlost pro určité podmínky dotazu, můžeme model vylepšit na fyzické úrovni a poskytnout:
-
Index (již máme index PK, takže jej nejprve vylepšíme, než přidáme druhý index), aby podporoval zahrnuté dotazy (ty založené na libovolném uspořádání { ProductId | DateTime | Status } mohou být poskytnuty indexem, aniž bychom museli přejděte na datové řádky). Což změní vztah Status::ProductStatus z Non-Identifying (přerušovaná čára) na Identifying type (plná čára).
-
Uspořádání PK je zvoleno na základě toho, že většina dotazů bude Time Series na základě Product⇢DateTime⇢Status.
-
Druhý index slouží ke zvýšení rychlosti dotazů na základě stavu.
-
V alternativním uspořádání je to obrácené; tj. většinou chceme aktuální stav všech Produktů.
-
Ve všech provedeních ProductStatus je sloupec DateTime v sekundárním indexu (nikoli PK) DESCending; nejnovější je první.
Poskytl jsem vámi požadovanou diskuzi. Samozřejmě musíte experimentovat se souborem dat přiměřené velikosti a dělat svá vlastní rozhodnutí. Pokud je zde něco, čemu nerozumíte, zeptejte se a já to rozšířím.
Odpovědi na komentáře
Nahlásit všechny produkty s aktuálním stavem 2
SELECT ProductId,
Description
FROM Product p,
ProductStatus ps
WHERE p.ProductId = ps.ProductId -- Join
AND StatusCode = 2 -- Request
AND DateTime = ( -- Current Status on the left ...
SELECT MAX(DateTime) -- Current Status row for outer Product
FROM ProductStatus ps_inner
WHERE p.ProductId = ps_inner.ProductId
)
-
ProductId
je indexováno, úvodní sloupec, obě strany -
DateTime
v Indexed, 2. sloupec v Covered Query Option -
StatusCode
je indexovaný, 3. sloupec ve volbě krytého dotazu -
Od
StatusCode
v Index je DESCending, k uspokojení vnitřního dotazu je zapotřebí pouze jedno načtení -
řádky jsou vyžadovány současně pro jeden dotaz; jsou blízko u sebe (kvůli Clstered Index); téměř vždy na stejné stránce kvůli krátké velikosti řádku.
Toto je běžný SQL, poddotaz, využívající sílu enginu SQL, zpracování relační sady. Je to jedna správná metoda , neexistuje nic rychlejšího a jakákoli jiná metoda by byla pomalejší. Jakýkoli nástroj pro vytváření přehledů vytvoří tento kód několika kliknutími, bez psaní.
Dvě data ve stavu produktu
Sloupce jako DateTimeFrom a DateTimeTo jsou hrubé chyby. Vezměme to v pořadí podle důležitosti.
-
Je to hrubá normalizační chyba. "DateTimeTo" je snadno odvozeno z jediného DateTime na dalším řádku; je tedy nadbytečný, duplicitní sloupec.
- Přesnost v tom nehraje roli:ta se dá snadno vyřešit pomocí DataType (DATE, DATETIME, SMALLDATETIME). Zda zobrazíte o sekundu méně, mikrosekundu nebo nanosekundu, je obchodní rozhodnutí; nemá to nic společného s uloženými daty.
-
Implementace sloupce DateTo je 100% duplikát (datum a čas dalšího řádku). To zabere dvojnásobek místa na disku . U velkého stolu by to bylo značné zbytečné plýtvání.
-
Vzhledem k tomu, že se jedná o krátký řádek, budete potřebovat dvakrát tolik logických a fyzických I/O pro čtení tabulky při každém přístupu.
-
A dvakrát více místa v mezipaměti (nebo jinak řečeno, do libovolného mezipaměti by se vešlo pouze poloviční počet řádků).
-
Zavedením duplicitního sloupce jste zavedli možnost chyby (hodnotu lze nyní odvodit dvěma způsoby:z duplicitního sloupce DateTimeTo nebo DateTimeFrom na dalším řádku).
-
Toto je také Anomálie aktualizace . Když aktualizujete jakékoli DateTimeFrom, je Aktualizováno, DateTimeTo předchozího řádku musí být načteno (žádný velký problém, protože je blízko) a Updated (velký problém, protože jde o dodatečné sloveso, kterému se lze vyhnout).
-
„Kratší“ a „kódovací zkratky“ jsou irelevantní, SQL je těžkopádný jazyk pro manipulaci s daty, ale SQL je vše, co máme (Jen se s tím vypořádej). Každý, kdo neumí kódovat poddotaz, by opravdu neměl kódovat. Každý, kdo duplikuje sloupec, aby si ulehčil drobné „obtíže“ s kódováním, by ve skutečnosti neměl modelovat databáze.
Všimněte si dobře, že pokud bylo zachováno pravidlo nejvyššího řádu (normalizace), celá sada problémů nižšího řádu je eliminována.
Přemýšlejte v podmínkách sad
-
Každý, kdo má „potíže“ nebo zažívá „bolest“ při psaní jednoduchého SQL, je při vykonávání své pracovní funkce ochromen. Vývojář obvykle není myšlení z hlediska množin a relační databáze je model orientovaný na sady .
-
Pro výše uvedený dotaz potřebujeme aktuální datum a čas; protože ProductStatus je množina stavů produktů v chronologickém pořadí, potřebujeme pouze nejnovější, neboli MAX (DateTime) z množiny patřící k produktu.
-
Nyní se podíváme na něco údajně „obtížného“, pokud jde o množiny . Pro přehled doby, po kterou byl každý produkt v určitém stavu:DateTimeFrom je dostupný sloupec a definuje horizontální mez, podmnožinu (můžeme vyloučit dřívější řádky); DateTimeTo je nejstarší z dílčí množiny stavů produktu.
SELECT ProductId,
Description,
[DateFrom] = DateTime,
[DateTo] = (
SELECT MIN(DateTime) -- earliest in subset
FROM ProductStatus ps_inner
WHERE p.ProductId = ps_inner.ProductId -- our Product
AND ps_inner.DateTime > ps.DateTime -- defines subset, cutoff
)
FROM Product p,
ProductStatus ps
WHERE p.ProductId = ps.ProductId
AND StatusCode = 2 -- Request
-
Přemýšlejte ve smyslu získání dalšího řádku je orientovaný na řádky, ne množinově orientované zpracování. Zmrzačení při práci s databází orientovanou na množiny. Nechte Optimizer, aby za vás všechno přemýšlel. Zkontrolujte svůj SHOWPLAN, to se krásně optimalizuje.
-
Neschopnost myslet v množinách , tedy omezení na psaní pouze jednoúrovňových dotazů, není rozumné ospravedlnění pro:implementaci masivní duplikace a anomálií aktualizací v databázi; plýtvání online zdroji a místem na disku; garantující poloviční výkon. Mnohem levnější je naučit se psát jednoduché poddotazy SQL pro získání snadno odvozených dat.