V moderních podmínkách je někdy velmi zvláštní slyšet „musíme sbalit databázi 1C – její objem přesahuje 50 GB“. Pokud by to dělali administrátoři systémů SAP R3 nebo Oracle e Business Suite nebo dokonce MS Dynamics Axe, pravděpodobně by je vyhodili. Pro 1C je to však „standardní praxe“.

U verzí souborů se příběh vrací k verzi 1C 7.7 s limitem 2 GB na velikost databáze. Nyní je limit 2 GB pouze na velikosti tabulky, velikost souboru se již může ukázat jako velmi, velmi malá. Je pravda, že pokud vaše databáze narostla do takové velikosti, pravděpodobně tam byla data aktivně zadána - možná musíte přemýšlet o klient-server?

Účelem tohoto článku je ve skutečnosti „odradit“ uživatele verze klient-server 1C od provádění kumulace databáze pomocí poněkud „pokročilejších“ technologií.

Konečné číslo je 30–40 tun, minimum oproti 20–25, pokud si koupíte pevný disk a získáte 500 GB místa navíc

Proto produkty jako
Jsou to pravděpodobně dobré produkty a plní své cíle. Jde jen o to, že struktura tabulek se mění od verze k verzi platformy. 1C nám o tom řekl více než jednou. Ve 14. vydání se objevil oddělovač dat a je to... s největší pravděpodobností toto zpracování již nebude vhodné pro 14. vydání. A je to nějak děsivé, nemluvě o porušení licenční smlouvy.

A i poté se najdou uživatelé, kteří „najednou náhle potřebovali“ vymazat data, kteří „chtěli jen opravit“ nějaké číslo, které „neovlivňuje sekvence“ v dokumentu uzavřeného období. A ještě horší je, když se ukáže, že se na tyto dokumenty někdo neustále díval za nějakým účelem, který zná jen on. Samozřejmě jsou to všechno jen chyby v metodice ovládání, ale přesto dojde k nespokojenosti uživatelů.


-
Otevřete Management Studio v seznamu databází, vyberte tu, kterou potřebujete, otevřete její vlastnosti.
- Přejděte na kartu „Skupiny souborů“, jak je znázorněno na obrázku, a přidejte další skupinu souborů (v příkladu se nazývá SEKUNDÁRNÍ)

- Přejděte na kartu „Soubory“ a přidejte nový soubor, pro který vybereme vytvořenou skupinu souborů. Tento soubor LZE NACHÁZET NA JINÉM DISKU


-
Nyní například pomocí zpracování: určíme, které tabulky můžeme bezpečně „darovat“ pomalejšímu (nebo naopak vše pomalejšímu, zbytek rychlejšímu) médiu. Platí zde pravidlo 80/20. 80 % operací se provádí s 20 % dat, takže přemýšlejte, které desky potřebujete rychle a které ne tolik. „Uložení doplňkových informací“, doklady pro zadání počátečních zůstatků, doklady, které již nepoužíváte, okamžitě je identifikujte jako ty, které lze přenést do „pomalé“ skupiny souborů.

Vyberte tabulku, kterou je třeba přesunout do jiné skupiny souborů - vyberte nabídku pro změnu tabulky (projektu) a ve vlastnostech změňte skupinu souborů:

indexy tabulek jsou také přeneseny do této skupiny souborů.
Poměrně pohodlný mechanismus pro distribuci tabulek přes disková pole různých rychlostí. To není v rozporu s licenční smlouvou, protože V řešení nevyužíváme přístup k datům a informační základně jinými prostředky než platformou 1C. Ukládání těchto dat organizujeme pouze pohodlným způsobem.


DBCC TRACEON (1807)

Tento příkaz napíšeme v Management Studiu, provedeme jej a můžeme úspěšně vytvářet databáze po síti. Instance SQL Serveru samozřejmě musí být spuštěna pod účtem domény a tento účet musí mít práva k požadované síťové složce.
Při použití tohoto příkazu ale buďte velmi opatrní, pokud vám při práci s databází vypadne síť, po dobu její nepřítomnosti nebude celá databáze přístupná. Ne nadarmo Microsoft tuto příležitost pro masové použití uzavřel. Obecně je tato funkce určena pro vytváření databází na NAS úložištích, což vřele doporučuji. Vhodný je také stabilní a spolehlivý souborový server, který má přímé spojení se serverem s MS SQL DBMS.
Více o dalších příznacích trasování si můžete přečíst v článku http://msdn.microsoft.com/ru-ru/library/ms188396.aspx
Tito. Část skupiny souborů lze dokonce uložit na síť a tam lze prostor na disku bez problémů rozšířit.

Samozřejmě je dobré tabulky rozdělit do různých skupin souborů... ale řeknete si, že tady je pár tabulek... které trvají od roku 2005... a už zabírají tucet gigabajtů... Kéž by v nich měli všechna data a dali samostatný disk, ale nechali ty aktuální.
Nebudete tomu věřit, ale je to také možné, i když ne příliš jednoduché:

Vytvořte funkci pro rozdělení podle data:

vytvořit funkci oddílu YearSection (datum a čas)
jako rozsah vpravo pro hodnoty ("20110101");

Vše před rokem 2011 spadne do jedné sekce, vše po roce do jiné.

Vytvoření schématu rozdělení

vytvořit schéma oddílů YearScheme
jako oddíl RokSekce do (SEKUNDÁRNÍ, PRIMÁRNÍ);

Tím říkáme, že všechna data do roku 11 skončí ve skupině souborů „Sekundární“ a poté ve skupině „Primární“

Nyní zbývá pouze přestavět tabulku rozdělením do sekcí. Nejjednodušší způsob, jak toho dosáhnout, je použít management studio, protože proces není jednoduchý. Musíte znovu sestavit seskupený index na tabulce (což je v podstatě samotná tabulka) a vybrat vytvořené schéma rozdělení pro index:

Na obrázku vidíte, že výběr není k dispozici - vše je v pořádku, Rozdělení tabulek je možné pouze ve verzi Enterprise MS SQL Server. Index clusteru je snadno rozlišitelný - obrázek se závorkami. Je vytvořen pro RN a všechny objekty 1C. U RN vždy existuje index clusteru podle období. Pro dokumenty a adresáře by bylo samozřejmě dobré vytvořit další, který obsahuje detaily, podle kterých bude dělení probíhat... ale to už by bylo porušení licenční smlouvy.

K tomu však nemusíte databázi sbalit, ale proveďte následující:
a) Vysvětlete všem, jak používat výběry, jak se ukládají, jak používat intervaly protokolu, jak se ukládají
b) Označte nepotřebná data ke smazání, pokud nenesou žádný význam (protistrany a položky, se kterými již nepracujete) – to přinese uživatelům více užitku než snížení. Pokud jsou prostředky k dispozici, nastavte automatické označování pro mazání nepoužívaných objektů a proveďte výchozí výběr v kódu programu, aby se objekty, které uživatelé nepotřebují – ty označené ke smazání – ve výchozím nastavení nezobrazovaly
c) Nastavte další užitečné „výchozí výběry“ – například tak, aby každý manažer ve výchozím nastavení viděl pouze své vlastní dokumenty. A pokud se chce podívat na dokumenty „soudruha“, musí výběr vypnout.

U všech podrobností, které se účastní výběru, nezapomeňte zaškrtnout políčko „Index s dodatečným objednáním“ - pak takové „vymoženosti“ neovlivní výkon systému.

Oracle DBMS má schopnost pohledy na oddíly. Základní myšlenka je jednoduchá. Nechte fyzickou tabulku rozdělit do několika tabulek (volitelně pomocí metod dělení tabulky) podle kritérií rozdělení, což zefektivňuje zpracování dotazů. Nazveme kritérium rozdělení rozdělovací predikát. Poté můžete vytvářet a přizpůsobovat pohledy, abyste uživatelům usnadnili přístup k datům v těchto tabulkách. Prezentační sekce je definována podle rozsahu hodnot klíč oddílu. Dotazy, které používají rozsah hodnot k načítání dat z oddílů zobrazení, budou přistupovat pouze k oddílům, které odpovídají rozsahům hodnot klíč oddílu.

Výřezy pohledu mohou být definovány predikáty dělení, zadané buď pomocí omezení CHECK nebo klauzule WHERE. Ukažme si, jak lze obě techniky aplikovat na příkladu mírně upravené tabulky Prodeje, na kterou jsme se podívali v předchozí části. Řekněme, že údaje o prodeji za kalendářní rok jsou umístěny ve čtyřech samostatných tabulkách, z nichž každá odpovídá čtvrtletí roku – Q1_Sales, Q2_Sales, Q3_Sales a Q4_Sales.

Příklad 20.14.

Pomocí omezení CHECK. Pomocí příkazu ALTER TABLE můžete přidat omezení do sloupce Datum prodeje (s_date) každé tabulky tak, aby její řádky odpovídaly jednomu ze čtvrtletí roku. Pohled prodeje, který poté vytvoříme, nám umožňuje přistupovat k těmto tabulkám, buď k jedné nebo všem dohromady.

ALTER TABLE Q1_Sales ADD CONSTRAINT C0 CHECK (s_date BETWEEN "jan-1-2002" AND "mar-31-2002"); ALTER TABLE Q2_Sales ADD CONSTRAINT C1 CHECK (s_date BETWEEN "1. dubna 2002" A "30. června 2002"); ALTER TABLE Q3_Sales ADD CONSTRAINT C2 check (s_date BETWEEN "jul-1-2002" AND "sept-30-2002"); ALTER TABLE Q4_Sales ADD CONSTRAINT C3 check (s_date BETWEEN "oct-1-2002" AND "dec-31-2002"); CREATE VIEW sales_v AS SELECT * FROM Q1_Sales UNION ALL SELECT * FROM Q2_Sales UNION ALL SELECT * FROM Q3_Sales UNION ALL SELECT * FROM Q4_Sales;

Výhoda tohoto zobrazit rozdělení je, že predikát omezení CHECK se nevyhodnocuje pro každý řádek dotazu. Takové predikáty brání vložení řádků, které nesplňují predikátové kritérium, do tabulek. Řetězce odpovídající predikátu dělení, se načítají z databáze rychleji.

Příklad 20.15.

Rozdělení pohledů pomocí klauzule WHERE. Vytvořme pohled pro stejné tabulky jako v příkladu výše.

CREATE VIEW sales_v AS SELECT * FROM Q1_Sales WHERE s_date BETWEEN "jan-1-2002" AND "mar-31-2002" UNION ALL SELECT * OD Q2_Sales WHERE s_date BETWEEN "duben-1-2002" A "jun-30-2000" UNION ALL SELECT * FROM Q3_Sales WHERE s_date BETWEEN "jul-1-2002" AND "sept-30-2002" UNION ALL SELECT * FROM Q4_Sales WHERE s_date BETWEEN "oct-1-2002" AND "dec-31-2002";

Metoda zobrazit rozdělení použití klauzule WHERE má některé nevýhody. Za prvé, kritérium dělení se za běhu kontroluje pro všechny řádky ve všech oddílech pokrytých dotazem. Za druhé, uživatelé mohou omylem vložit řádek do nesprávné sekce, tzn. Vložte řádek z prvního čtvrtletí do třetího čtvrtletí, což povede k nesprávnému výběru dat pro tato čtvrtletí.

Tato technika má také výhody oproti použití omezení CHECK. Sekci, která odpovídá predikátu WHERE, můžete umístit do vzdálené databáze. Níže je uveden fragment definice odpočinku.

Při rozhodování o tvorbě je třeba mít na paměti následující faktory.

  • a mazání dat, pracujte na úrovni sekce, nikoli na úrovni celé základní tabulky.
  • Přístup do jedné ze sekcí nemá žádný vliv na data v ostatních sekcích.
  • Oracle DBMS má nezbytné vestavěné schopnosti pro rozpoznávání rozdělené pohledy.
  • Rozdělení pohledů velmi užitečné při práci s tabulkami obsahujícími velké množství historických dat.

Rozdělovací tabulky v DBMS rodiny MS SQL Server

Vytváření dělených tabulek

Podporuje také DBMS rodiny MS SQL Server dělení tabulky, indexy a pohledy. Na rozdíl od rodiny DBMS Oracle však dělení v DBMS rodiny MS SQL Server se provádí podle jednotného schématu.

V MS SQL Server jsou všechny tabulky a indexy v databázi považovány za rozdělené, i když se skládají pouze z jedné sekce. Oddíly ve skutečnosti představují základní organizační jednotku ve fyzické architektuře tabulek a indexů. To znamená, že logická a fyzická architektura tabulek a indexů, které obsahují více oddílů, přesně zrcadlí architekturu tabulek a indexů, které se skládají z jednoho oddílu.

Dělení sekcí tabulky a indexy jsou pevně nastaveny na úrovni řádků ( dělení sloupcový není povolen) a umožňuje přístup přes jediný vstupní bod (název tabulky nebo indexový název), takže kód aplikace nemusí znát počet oddílů. Dělení sekcí lze provést na základní tabulce, stejně jako na indexech s ní spojených.

Každý rozsah hodnot v sekci má hranice, které jsou definovány v příkazu FOR VALUES. Pokud bylo datum prodeje 23. června 2006, pak bude linka uložena v sekci 2 (P2).

Nyní pojďme tvořit schéma rozdělení. Schéma rozdělení mapuje sekce na různé skupiny souborů (pojmenované MyFilegroup1, MyFilegroup2, MyFilegroup3, MyFilegroup4), jak je znázorněno v následujícím příkazu:

VYTVOŘIT SCHÉMA ODDĚLENÍ MyPartitionScheme JAKO MyPartitionFunction TO (MyFilegroup1, MyFilegroup2, MyFilegroup3, MyFilegroup4)

MyPartitionScheme je název rozdělovací schémata a název MyPartitionFunction definuje rozdělovací funkce. Tento příkaz zobrazí data v oddílech, které jsou přidruženy k jedné nebo více skupinám souborů. Datové řádky s hodnotami sloupce Date_of_Event date před 1. 1. 2005 jsou přidruženy k MyFilegroup1 . Řádky v tomto sloupci s hodnotami většími nebo rovnými 1/1/05 a před 1/1/07 jsou přiřazeny k MyFilegroup2 . Řádky s hodnotami většími nebo rovnými 1/1/07 a před 1/1/09 jsou přidruženy k MyFilegroup3 . Všechny ostatní řádky s hodnotami většími nebo rovnými 1/1/09 jsou přidruženy k MyFilegroup4 .

Pro každou sadu hraničních hodnot (které jsou určeny podmínkou FOR VALUES rozdělovací funkce) počet sekcí bude roven "Počet hraničních hodnot" + 1 sekce. Předchozí příkaz CREATE PARTITION SCHEME obsahuje tři omezení a čtyři oblasti. Bez ohledu na to, zda jsou oddíly vytvořeny s RANGE RIGHT nebo RANGE LEFT , počet oddílů bude vždy "Počet hraničních hodnot" + 1, až do maximálního počtu 1000 oddílů na tabulku.

Nyní můžeme tvořit dělená tabulka fakta "Prodej" (PRODEJ). Stvoření dělená tabulka se příliš neliší od vytvoření běžné tabulky, stačí uvést název rozdělovací schémata ve stavu ON, jak je znázorněno v příkazu níže.

VYTVOŘIT TABULKU PRODEJ (Sales_ШВ bigint identita (1, 1) primární není seskupená NOT NULL, Cust_ID bigint null, Prod_ID bigint null, Store_ID bigint null, REG_ID char(10) null, Time_of_Event time null, Quantity integer not null ,2) not null, Date_of_Event date NOT NULL) ON MyPartitionScheme (Date_of_Event)

Definování jména rozdělovací schémata, návrhář určí, že tato tabulka je indexována. To umožňuje návrháři navrhnout strukturu indexu na základě rozdělených dat spíše než na datech celé tabulky. Vytváření rozdělených indexů vyžaduje vytvoření samostatných vyvážených stromů na rozdělených indexech. Rozdělením indexů vznikají menší indexy a administrátor databáze nebo se úložiště dat snadněji udržuje při změně, přidávání a mazání dat.

Při vytváření rozdělených indexů můžete vytvořit zarovnaný nebo nezarovnané indexy. Zarovnané indexy poskytují přímé spojení s rozdělenými daty v tabulce. V případě nezarovnaných indexů se vybere jiný schéma rozdělení.

Ze dvou metod je upřednostňován zarovnaný index a je vybrán jako výchozí, pokud po vytvoření dělená tabulka indexy jsou vytvářeny bez určení jiného rozdělovací schémata. Použití zarovnaných indexů poskytuje nezbytnou flexibilitu pro vytváření dalších oddílů v tabulce a také umožňuje převést vlastnictví konkrétního oddílu na jinou tabulku. K vyřešení většiny problémů souvisejících dělení, stačí zažádat o indexy schéma rozdělení tabulky.

Příklad. 20.19.

Vytvořme oddíl neshlukovaný index na rozdělené tabulka "Prodej" (PRODEJ) z předchozího příkladu 20.18.

VYTVOŘIT SCHÉMA ODDĚLENÍ Index_primary_Left_Scheme JAKO ODDIEL Index_Left_Partition VŠECHNY DO ()

Nyní spusťte příkaz create index, jak je znázorněno níže.

VYTVOŘIT NEZAHRNUTÝ INDEX cl_multiple_partition ON multiple_partition(Cust_ID) ON Index_primary_Left_Scheme (Cust_ID)

V tomto neshlukovaný index sloupec "Customer ID" (Cust_ID) se používá jako indexový klíč, což není klíč oddílu"Prodejní" tabulky (PRODEJ).

Rozhodnutí o rozdělení indexů jsou akceptovány projektantem datového skladu ve fázi návrhu nebo správcem datového skladu ve fázi provozu datového úložiště. Účel rozdělení indexů je buď zajistit výkon dotazů, nebo zjednodušit procedury údržby indexu.

V tomto článku předvedu specifika plánů provádění dotazů při přístupu k děleným tabulkám. Všimněte si, že existuje velký rozdíl mezi rozdělenými tabulkami (které byly k dispozici pouze v SQL Server 2005) a rozdělenými pohledy (které byly k dispozici v SQL Server 2000 a jsou stále dostupné v SQL Server 2005 a novějších verzích). Specifika plánů dotazů pro rozdělené pohledy předvedu v jiném článku.

Zobrazit tabulku

Vytvořme jednoduchou dělenou tabulku:

vytvořit oddílovou funkci pf(int) jako rozsah pro hodnoty (0, 10, 100)

vytvořit schéma oddílů ps jako oddíl pf all to ()

vytvořit tabulku t (a int, b int) na ps(a)

Tento skript vytvoří tabulku se čtyřmi oddíly. SQL Server přiřadil hodnoty k ID každého ze čtyř oddílů, jak je uvedeno v tabulce:

PtnId Hodnoty
1 t.a<= 0
2 0 < t.a <= 10
3 10 < t.a <= 100
4 100 < t.a

Nyní se podíváme na plán dotazů, který by optimalizátor přinutil použít prohledávání tabulky:


……|–Konstantní skenování(HODNOTY:(((1)),((2)),((3)),((4))))
…….|–Skenování tabulky(OBJECT:([t]))

Ve výše uvedeném plánu SQL Server explicitně specifikuje všechna ID oddílů v příkazu "Constant Scan", který implementuje skenování tabulky a dodává data operátoru spojení vnořené smyčky. Zde stojí za to připomenout, že operátor spojení vnořené smyčky prochází vnitřní tabulkou (v tomto případě úplným skenováním tabulky) jednou pro každou hodnotu z vnější tabulky (v našem případě "Constant Scan"). Skenujeme tedy tabulku čtyřikrát; jednou pro každé ID sekce.

Je třeba také poznamenat, že spojení vnořených smyček jasně ukazuje, že vnější tabulka jsou hodnoty sloupce, kde jsou uložena ID oddílů. I když to není hned vidět v textovém zobrazení prováděcího plánu (bohužel někdy si této informace nevšimneme), skenování tabulky používá sloupec s ID sekcí, které jsou vybrány pro provedení skenování a určuje, který úsek se má provést skenovat. Tyto informace jsou vždy k dispozici v grafickém plánu provádění (je třeba se podívat na vlastnosti operátoru zobrazení tabulky) a také v reprezentaci plánu provádění dotazu ve formátu XML:

Filtrování statické sekce

Zvažte následující dotaz:

vyberte * od t kde a< 100

|–Vnořené smyčky(vnitřní spojení, VNĚJŠÍ REFERENCE:() ID PARTITION:())
…….|–Constant Scan(VALUES:(((1)),((2)),((3))))
<(100)) PARTITION ID:())

predikát "a"<100» явно исключает все строки для секции со значением идентификатора равным 4. В данном случае, нет смысла в просмотре соответствующей секции, поскольку ни одна из строк этой секции не удовлетворяет условию предиката. Оптимизатор учитывает этот факт и исключает эту секцию из плана исполнения запроса. В операторе «Constant Scan» указаны только три секции. У нас принято называть это статической фильтрацией секций (static partition elimination), поскольку мы знаем, что во время компиляции список просматриваемых секций остаётся статичным.

Pokud statické filtrování odstraní všechny oddíly kromě jednoho, nebudeme vůbec potřebovat operátory Constant Scan a Nested Loops Join:

vyberte * od t kde a< 0

|–Skenování tabulky(OBJEKT:([t]), KDE:([t].[a]<(0)) PARTITION ID:((1)))

Všimněte si, že příkaz "ID PARTITION:((1))", který specifikuje ID oddílu, který má být zkontrolován, je nyní součástí příkazu Table Scan.

Dynamické filtrování sekcí

V některých případech SQL Server nemůže určit, že se složení prohlížených oddílů nezmění v době kompilace, ale může vidět, že některé oddíly lze vyloučit.

vyberte * od t kde a< @i

|–Vnořené smyčky(vnitřní spojení, VNĚJŠÍ REFERENCE:() ID PARTITION:())
…….|–Filtrovat(KDE:(<=RangePartitionNew([@i],(0),(0),(10),(100))))
…….| |–Konstantní skenování(HODNOTY:(((1)),((2)),((3)),((4))))
…….|–Skenování tabulky(OBJECT:([t]), WHERE:([t].[a]<[@i]) PARTITION ID:())

Toto je parametrizovaný dotaz. Vzhledem k tomu, že před provedením neznáme hodnotu parametru (skutečnost, že jako parametr ve stejné dávce používám konstantu, na situaci nic nemění), není možné určit hodnotu identifikátoru sekce pro „Constant Scan“ ” operátor ve fázi kompilace. Možná se budete muset podívat pouze na oddíl 1, nebo to budou oddíly 1 a 2 a tak dále. Proto jsou v tomto příkazu specifikována všechna čtyři ID sekcí a používáme filtrování ID sekcí za běhu. Říkáme tomu dynamické odstranění oddílů.

Filtr porovná každý identifikátor sekce s výsledkem speciální funkce „RangePartitionNew“. Tato funkce vypočítá výsledky aplikace rozdělovací funkce na hodnotu parametru. Argumenty této funkce (zleva doprava) jsou:

  • hodnotu (v tomto případě parametr @i), kterou chceme zobrazit na ID sekce;
  • booleovský příznak udávající, zda rozdělovací funkce zobrazuje levé (0) nebo pravé (1) hraniční hodnoty;
  • hodnoty hranice sekce (v tomto případě jsou to 0, 10 a 100).

V tomto příkladu, protože @i je 0, je výsledek "RangePartitionNew" 1. Skenujeme tedy pouze oddíl s ID 1. Všimněte si, že na rozdíl od příkladu filtrování statického oddílu, přestože skenujeme pouze jeden oddíl, -stále máme „Constant Scan“ a „Nested Loops Join“. Důvod, proč potřebujeme tato prohlášení, je ten, že neznáme sekce, které budou skenovány až do fáze provedení.

V některých případech může optimalizátor již při kompilaci určit, že budeme skenovat pouze jednu sekci, i když nedokáže určit kterou. Pokud například dotaz používá predikát ekvivalence klíče oddílu, pak víme, že tuto podmínku může splnit pouze jeden oddíl. Proto, přestože jsme museli mít dynamické filtrování sekcí, již nepotřebujeme operátory „Constant Scan“ a „Nested Loops Join“. Příklad:

vyberte * z t, kde a = @i

|–Skenování tabulky(OBJECT:([t]), WHERE:([t].[a]=[@i]) ID ODDĚLENÍ:(RangePartitionNew([@i],(0),(0),(10) ),(100))))

Kombinace filtrování statické a dynamické sekce

SQL Server může kombinovat statické a dynamické filtrování oddílů v jediném plánu dotazů:

vyberte * z t, kde a > 0 a a< @i

|–Vnořené smyčky(vnitřní spojení, VNĚJŠÍ REFERENCE:() ID PARTITION:())
……|–Filtr(KDE:(<=RangePartitionNew([@i],(0),(0),(10),(100))))
……| |–Constant Scan(VALUES:(((2)),((3)),((4))))
……|–Skenování tabulky(OBJECT:([t]), WHERE:([t].[a]<[@i] AND [t].[a]>(0)) ID ODDĚLENÍ:())

Všimněte si, že v posledním plánu je statické filtrování sekce ID=1 pomocí „Constant Scan“ a existuje také dynamické filtrování pro další sekce definované predikáty.

$oddíl

Funkci RangePartitionNew můžete explicitně zavolat pomocí $partition:

vyberte *, $partition.pf(a) z t

|–Vypočítat skalární(DEFINE:(=RangePartitionNew([t].[a],(0),(0),(10),(100))))
……|–Vnořené smyčky (Vnitřní spojení, VNĚJŠÍ ODKAZY:() ID ODDĚLENÍ:())
…..|–Konstantní skenování(HODNOTY:(((1)),((2)),((3)),((4))))
…..|–Skenování tabulky(OBJEKT:([t]))

Charakteristickým rysem tohoto plánu provádění dotazů je vzhled operátoru Compute Scalar.

dodatečné informace

Dobrý večer/den/ráno, milí habrapeople! Pokračujeme ve vývoji a rozšiřování blogu o mém oblíbeném open source rdbms Postgresql. Jako zázrakem se stalo, že téma dnešního tématu zde ještě nikdy nebylo nastoleno. Musím říct, že rozdělení v postgresql je v dokumentaci velmi dobře popsáno, ale opravdu mě to zastaví?).

Úvod

Obecně je dělení obecně chápáno ne jako nějaký druh technologie, ale spíše jako přístup k návrhu databází, který se objevil dávno předtím, než DBMS začaly podporovat tzv. rozdělené tabulky. Myšlenka je velmi jednoduchá - rozdělte stůl na několik menších částí. Existují dva podtypy – horizontální a vertikální dělení.
Horizontální dělení
Části tabulky obsahují různé řádky. Řekněme, že máme tabulku protokolů pro nějakou abstraktní aplikaci – LOGS. Můžeme to rozdělit na části - jedna pro protokoly za leden 2009, další za únor 2009 atd.
Vertikální rozdělení
Části tabulky obsahují různé sloupce. Najít aplikaci pro vertikální dělení (když je to vlastně opodstatněné) je poněkud obtížnější než pro horizontální dělení. Jako sférický kůň navrhuji zvážit tuto možnost: tabulka NEWS má sloupce ID, SHORTTEXT, LONGTEXT a pole LONGTEXT je třeba používat mnohem méně často než první dva. V tomto případě má smysl tabulku NEWS rozdělit podle sloupců (vytvořit dvě tabulky pro SHORTTEXT a LONGTEXT, propojené primárními klíči + vytvořit pohled NEWS obsahující oba sloupce). Když tedy potřebujeme pouze popis novinky, nemusí DBMS číst celý text novinky z disku.
Podpora pro dělení v moderních DBMS
Většina moderních DBMS podporuje dělení tabulek v té či oné podobě.
  • Věštec- podporuje dělení od verze 8. Práce se sekcemi je na jednu stranu velmi jednoduchá (nemusíte o nich vůbec přemýšlet, pracujete jako s běžnou tabulkou*) a na druhou stranu je vše velmi flexibilní. Sekce lze rozdělit na „pododdíly“, odstranit, rozdělit, přenést. Jsou podporovány různé možnosti indexování dělené tabulky (globální index, dělený index). Odkaz na dlouhý popis.
  • Microsoft SQL Server- podpora pro dělení se objevila nedávno (v roce 2005). První dojem z používání je "No, konečně!! :)", druhý "Funguje, vše se zdá být v pořádku." Dokumentace na msdn
  • MySQL- podporuje od verze 5.1. Velmi dobrý popis na Habrého
  • A tak dále…
*-Lžu, samozřejmě, existuje standardní sada obtíží - vytvoření nové sekce včas, vyhození staré atd., Ale nějak je vše jednoduché a jasné.

Rozdělení v Postgresql

Rozdělovací tabulky v postgresql se v implementaci mírně liší od jiných databází. Základem pro rozdělení na oddíly je dědičnost tabulek (což je unikátní pro postgresql). To znamená, že musíme mít hlavní tabulku a její sekce budou následnými tabulkami. Budeme uvažovat o rozdělení na příkladu úlohy blízké realitě.
Formulace problému
Databáze slouží ke sběru a analýze dat o návštěvnících stránek/stránek. Objemy dat jsou dostatečně velké, aby bylo možné uvažovat o rozdělení. Ve většině případů analýza používá data z posledního dne.
1. Vytvořte hlavní tabulku:
VYTVOŘTE TABULKU analytics.events

user_id UUID NENÍ NULL,
event_type_id SMALLINT NOT NULL ,
event_time TIMESTAMP DEFAULT now() NOT NULL,
url VARCHAR (1024) NOT NULL,
referrer VARCHAR (1024),
IP INET NENÍ NULL
);

2. Rozdělíme podle dne pomocí pole event_time. Pro každý den vytvoříme novou sekci. Sekce pojmenujeme podle pravidla: analytics.events_DDMMYYYY. Zde je například sekce k 1. lednu 2010.
CREATE TABLE analytics.events_01012010
event_id BIGINT DEFAULT nextval("analytics.seq_events" ) PRIMÁRNÍ KLÍČ ,
KONTROLA (čas_události >= ČASOVÉ ZNÁMKA "2010-01-01 00:00:00" A čas_události< TIMESTAMP "2010-01-02 00:00:00" )
) INHERITS(analytics.events);

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.


Při vytváření sekce explicitně nastavíme pole event_id (PRIMARY KEY se nedědí) a na pole event_time vytvoříme CHECK CONSTRAINT, abychom nevkládali zbytečné věci.

3. Vytvořte index v poli event_time. Když rozdělujeme tabulku, očekáváme, že většina dotazů na tabulku událostí bude používat podmínku v poli event_time, takže index v tomto poli nám hodně pomůže.

CREATE INDEX events_01012010_event_time_idx ON analytics.events_01012010 POMOCÍ btree(čas_události);

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.


4. Chceme zajistit, aby data po vložení do hlavní tabulky skončila v sekci k tomu určené. K tomu uděláme následující trik – vytvoříme trigger, který bude řídit datové toky.
VYTVOŘTE NEBO NAHRAĎTE FUNKCI analytics.events_insert_trigger()
VRÁTÍ SPUŠTĚČ JAKO $$
ZAČÍT
POKUD (NEW .event_time >= TIMESTAMP "2010-01-01 00:00:00" AND
NOVÉ .event_time< TIMESTAMP "2010-01-02 00:00:00" ) THEN
INSERT INTO analytics.events_01012010 VALUES (NEW .*);
JINÝ
ZVÝŠIT VÝJIMKU "Datum % je mimo rozsah. Opravte analytics.events_insert_trigger", NOVINKA .čas_události;
END IF ;
RETURN NULL;
KONEC ;
$$
JAZYK plpgsql;

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.


CREATE TRIGGER events_before_insert
PŘED VLOŽENÍM NA analytics.events
PRO KAŽDÝ ŘÁDEK PROVEĎTE POSTUP analytics.events_insert_trigger();

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.

5. Vše je připraveno, nyní máme rozdělenou tabulku s názvem analytics.events. Můžeme začít zuřivě analyzovat její data. Mimochodem, omezení CHECK jsme vytvořili nejen kvůli ochraně sekcí před nesprávnými daty. Postgresql je může použít při vytváření plánu dotazů (avšak s živým indexem na event_time bude zisk minimální), stačí použít direktivu constraint_exclusion:

SET omezení_vyloučení = on ;
SELECT * FROM analytics.events WHERE čas_události > CURRENT_DATE ;

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.

Konec prvního dílu
Tak co máme? Pojďme bod po bodu:
1. Tabulka událostí, rozdělená do sekcí, analýza dostupných dat za poslední den se stává jednodušší a rychlejší.
2. Hrůza z uvědomění si, že tohle všechno je potřeba nějak podpořit, sekce je potřeba vytvářet včas, nezapomenout patřičně změnit spoušť.

Jak snadno a bezstarostně pracovat s rozdělenými tabulkami vám řeknu v druhé části.

UPD1: Nahrazeno dělení dělením
UPD2:
Na základě komentáře jednoho ze čtenářů, který bohužel nemá účet na Habré:
Existuje několik problémů spojených s dědičností, které je třeba vzít v úvahu při navrhování. Oddíly nedědí primární klíč a cizí klíče ve svých sloupcích. To znamená, že při vytváření sekce musíte explicitně vytvořit PRIMÁRNÍ KLÍČ a CIZÍ KLÍČE pro sloupce sekce. Sám bych rád poznamenal, že vytvoření FOREIGN KEY na sloupcích rozdělené tabulky není nejlepší způsob. Ve většině případů je rozdělená tabulka „tabulkou faktů“ a sama o sobě odkazuje na „dimenzi“ tabulky.

Dobrý večer/den/ráno, milí habrapeople! Pokračujeme ve vývoji a rozšiřování blogu o mém oblíbeném open source rdbms Postgresql. Jako zázrakem se stalo, že téma dnešního tématu zde ještě nikdy nebylo nastoleno. Musím říct, že rozdělení v postgresql je v dokumentaci velmi dobře popsáno, ale opravdu mě to zastaví?).

Úvod

Obecně je dělení obecně chápáno ne jako nějaký druh technologie, ale spíše jako přístup k návrhu databází, který se objevil dávno předtím, než DBMS začaly podporovat tzv. rozdělené tabulky. Myšlenka je velmi jednoduchá - rozdělte stůl na několik menších částí. Existují dva podtypy – horizontální a vertikální dělení.
Horizontální dělení
Části tabulky obsahují různé řádky. Řekněme, že máme tabulku protokolů pro nějakou abstraktní aplikaci – LOGS. Můžeme to rozdělit na části - jedna pro protokoly za leden 2009, další za únor 2009 atd.
Vertikální rozdělení
Části tabulky obsahují různé sloupce. Najít aplikaci pro vertikální dělení (když je to vlastně opodstatněné) je poněkud obtížnější než pro horizontální dělení. Jako sférický kůň navrhuji zvážit tuto možnost: tabulka NEWS má sloupce ID, SHORTTEXT, LONGTEXT a pole LONGTEXT je třeba používat mnohem méně často než první dva. V tomto případě má smysl tabulku NEWS rozdělit podle sloupců (vytvořit dvě tabulky pro SHORTTEXT a LONGTEXT, propojené primárními klíči + vytvořit pohled NEWS obsahující oba sloupce). Když tedy potřebujeme pouze popis novinky, nemusí DBMS číst celý text novinky z disku.
Podpora pro dělení v moderních DBMS
Většina moderních DBMS podporuje dělení tabulek v té či oné podobě.
  • Věštec- podporuje dělení od verze 8. Práce se sekcemi je na jednu stranu velmi jednoduchá (nemusíte o nich vůbec přemýšlet, pracujete jako s běžnou tabulkou*) a na druhou stranu je vše velmi flexibilní. Sekce lze rozdělit na „pododdíly“, odstranit, rozdělit, přenést. Jsou podporovány různé možnosti indexování dělené tabulky (globální index, dělený index). Odkaz na dlouhý popis.
  • Microsoft SQL Server- podpora pro dělení se objevila nedávno (v roce 2005). První dojem z používání je "No, konečně!! :)", druhý "Funguje, vše se zdá být v pořádku." Dokumentace na msdn
  • MySQL- podporuje od verze 5.1.
  • A tak dále…
*-Lžu, samozřejmě, existuje standardní sada obtíží - vytvoření nové sekce včas, vyhození staré atd., Ale nějak je vše jednoduché a jasné.

Rozdělení v Postgresql

Rozdělovací tabulky v postgresql se v implementaci mírně liší od jiných databází. Základem pro rozdělení na oddíly je dědičnost tabulek (což je unikátní pro postgresql). To znamená, že musíme mít hlavní tabulku a její sekce budou následnými tabulkami. Budeme uvažovat o rozdělení na příkladu úlohy blízké realitě.
Formulace problému
Databáze slouží ke sběru a analýze dat o návštěvnících stránek/stránek. Objemy dat jsou dostatečně velké, aby bylo možné uvažovat o rozdělení. Ve většině případů analýza používá data z posledního dne.
1. Vytvořte hlavní tabulku:
VYTVOŘTE TABULKU analytics.events

user_id UUID NENÍ NULL,
event_type_id SMALLINT NOT NULL ,
event_time TIMESTAMP DEFAULT now() NOT NULL,
url VARCHAR (1024) NOT NULL,
referrer VARCHAR (1024),
IP INET NENÍ NULL
);

2. Rozdělíme podle dne pomocí pole event_time. Pro každý den vytvoříme novou sekci. Sekce pojmenujeme podle pravidla: analytics.events_DDMMYYYY. Zde je například sekce k 1. lednu 2010.
CREATE TABLE analytics.events_01012010
event_id BIGINT DEFAULT nextval("analytics.seq_events" ) PRIMÁRNÍ KLÍČ ,
KONTROLA (čas_události >= ČASOVÉ ZNÁMKA "2010-01-01 00:00:00" A čas_události< TIMESTAMP "2010-01-02 00:00:00" )
) INHERITS(analytics.events);

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.


Při vytváření sekce explicitně nastavíme pole event_id (PRIMARY KEY se nedědí) a na pole event_time vytvoříme CHECK CONSTRAINT, abychom nevkládali zbytečné věci.

3. Vytvořte index v poli event_time. Když rozdělujeme tabulku, očekáváme, že většina dotazů na tabulku událostí bude používat podmínku v poli event_time, takže index v tomto poli nám hodně pomůže.

CREATE INDEX events_01012010_event_time_idx ON analytics.events_01012010 POMOCÍ btree(čas_události);

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.


4. Chceme zajistit, aby data po vložení do hlavní tabulky skončila v sekci k tomu určené. K tomu uděláme následující trik – vytvoříme trigger, který bude řídit datové toky.
VYTVOŘTE NEBO NAHRAĎTE FUNKCI analytics.events_insert_trigger()
VRÁTÍ SPUŠTĚČ JAKO $$
ZAČÍT
POKUD (NEW .event_time >= TIMESTAMP "2010-01-01 00:00:00" AND
NOVÉ .event_time< TIMESTAMP "2010-01-02 00:00:00" ) THEN
INSERT INTO analytics.events_01012010 VALUES (NEW .*);
JINÝ
ZVÝŠIT VÝJIMKU "Datum % je mimo rozsah. Opravte analytics.events_insert_trigger", NOVINKA .čas_události;
END IF ;
RETURN NULL;
KONEC ;
$$
JAZYK plpgsql;

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.


CREATE TRIGGER events_before_insert
PŘED VLOŽENÍM NA analytics.events
PRO KAŽDÝ ŘÁDEK PROVEĎTE POSTUP analytics.events_insert_trigger();

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.

5. Vše je připraveno, nyní máme rozdělenou tabulku s názvem analytics.events. Můžeme začít zuřivě analyzovat její data. Mimochodem, omezení CHECK jsme vytvořili nejen kvůli ochraně sekcí před nesprávnými daty. Postgresql je může použít při vytváření plánu dotazů (avšak s živým indexem na event_time bude zisk minimální), stačí použít direktivu constraint_exclusion:

SET omezení_vyloučení = on ;
SELECT * FROM analytics.events WHERE čas_události > CURRENT_DATE ;

* Tento zdrojový kód byl zvýrazněn pomocí Zvýrazňovače zdrojového kódu.

Konec prvního dílu
Tak co máme? Pojďme bod po bodu:
1. Tabulka událostí, rozdělená do sekcí, analýza dostupných dat za poslední den se stává jednodušší a rychlejší.
2. Hrůza z uvědomění si, že tohle všechno je potřeba nějak podpořit, sekce je potřeba vytvářet včas, nezapomenout patřičně změnit spoušť.

Jak snadno a bezstarostně pracovat s rozdělenými tabulkami vám řeknu v druhé části.

UPD1: Nahrazeno dělení dělením
UPD2:
Na základě komentáře jednoho ze čtenářů, který bohužel nemá účet na Habré:
Existuje několik problémů spojených s dědičností, které je třeba vzít v úvahu při navrhování. Oddíly nedědí primární klíč a cizí klíče ve svých sloupcích. To znamená, že při vytváření sekce musíte explicitně vytvořit PRIMÁRNÍ KLÍČ a CIZÍ KLÍČE pro sloupce sekce. Sám bych rád poznamenal, že vytvoření FOREIGN KEY na sloupcích rozdělené tabulky není nejlepší způsob. Ve většině případů je rozdělená tabulka „tabulkou faktů“ a sama o sobě odkazuje na „dimenzi“ tabulky.