Hledám uložení tříděného seznamu do databáze. Chci provádět následující operace efektivně.
Jednoduchá metoda, na kterou bych mohl myslet, je uložit do tabulky nějaký atribut „pozice“ a dotaz podle třídění podle tohoto atributu. V této metodě se však vkládání/úprava záznamu s hodností stává nákladnou operací. Existuje lepší metoda?
Konkrétně se chystám implementovat tabulku pomocí Amazonu SimpleDB. Užitečná by však měla být i obecná odpověď na relační databázi.
Aktualizace profilu zatížení:
Protože to plánuji pro webovou aplikaci, záleží na počtu uživatelů, kteří aplikaci používají.
Pokud jsou aktivní uživatelé 100 000 (super optimismus: P), pak by byl můj přibližný odhad za den
500k vybere, 100k vloží a odstraní, 500k aktualizace
Očekával bych, že stůl poroste celkem na 500 tisíc.
Hledám optimalizaci pro aktualizace, vkládání a operace Porovnání. Pořadí položek se bude neustále měnit a já musím tabulku aktualizovat.
Pokud hodnost není zcela libovolná, ale je místo toho odvozitelná od nějakého jiného majetku (např. Jména, skóre hráče atd.), Pak se dobře podívejte na Joelova odpověď .
Pokud je libovolná vlastnost vašich dat, měla by být uložena jako sloupec v tabulce záznamů. Za předpokladu, že Amazon SimpleDB je podobný typickému RDBMS, můžete tento sloupec indexovat a rychle uspokojit všechny výše uvedené dotazy pomocí vhodné strategie indexování. To je normální u RDBMS.
Vzhledem k tomu, že očekáváte vysokou aktivitu při vkládání a aktualizaci, ale také relativně vysokou aktivitu při čtení, doporučujeme provádět následující akce:
INCLUDE
- pořadí, nebo jen zaznamenat, pokud jste se seskupili do pozice) by vyhovoval dotazu 7.FILLFACTOR
na serveru SQL). To je obzvláště důležité, pokud se seskupujete v pořadí.Pokud očekáváte 100K + čtení v tabulce o velikosti 100 K +, nedoporučuji používat přístup propojeného seznamu. Na tyto velikosti se nebude dobře přizpůsobovat.
Obecně používám metodu „rank“, kterou popisuješ. Namísto toho, abych se pokoušel aktualizovat řádky, když bylo potřeba položky znovu uspořádat, jsem často dokázal uniknout odstraněním všech záznamů v seznamu a opětovným vložením nových položek ve správném pořadí. Tato metoda je jasně optimalizována pro vyhledávání.
Alternativním přístupem by bylo modelování záznamů jako propojeného seznamu pomocí sloupce reflexního cizího klíče „předchůdce“ v tabulce:
ID setID item predecessor
--- ------ ------ ------------
1 1 Apple null
2 1 Orange 1
3 2 Cucumber null
4 1 Pear 2
5 1 Grape 4
6 2 Carrot 3
Můžete snadno načíst seznam a přidávat a odebírat položky s malou režií, ale dostat záznamy do správného pořadí bude složité. Možná existuje chytrý způsob, jak to udělat v jediném dotazu, pravděpodobně se spoustou aliasovaných tabulkových připojení.
Tento přístup používám často, když modeluji vztah ve stylu stromu (kategorie, složky, sady a podmnožiny). Obecně jsem měl rekurzivní funkci nějakého druhu k rekonstrukci celého stromu v mé aplikaci.
Myslím, že je třeba ložit vlastnost nebo vlastnosti, které se používají pro výpočet pořadí a poté nad nimi vytvořit index. Proč se pokusit donutit databázi fyzicky ukládat data v pořadí podle pořadí nebo pomocí ručně spravovaného propojeného seznamu, proč nenechat databázový stroj dělat to, co bylo navrženo?
Toto jsou omezení non-RDBMS jako simpleDB. Požadované funkce nemohou být implementovány na straně DB v simpleDB, musí být implementovány z programovací strany/aplikace.
Pro RDBMS jako SQL server
, funkce, které požadujete, jsou pro seskupený index základní.
Before (x, n) - Vraťte záznamy „n“ před záznamem x v seřazeném seznamu. > Vyberte nejlepší výsledky n, kde x je menší než hodnota a seřazeno podle klauzule.
After (x, n) - Vraťte záznamy „n“, které následují po záznamu x v seřazeném seznamu. > Vyberte nejlepší výsledky n, kde x větší než hodnota a pořadí podle klauzule.
First (n) - Vrátí první 'n' záznamy z seřazeného seznamu. > Vyberte nejlepší výsledky n.
Last (n) - Vrátí poslední 'n' záznamy z seřazeného seznamu. > Vyberte nejlepší výsledky n po objednávce podle popisu.
Zde je to, co jsem použil k přehodnocení své Postgres tabulky po každém vložení:
CREATE OR REPLACE FUNCTION re_rank_list() RETURNS trigger AS $re_rank_list$
DECLARE
temprow record;
row_idx integer := 1;
BEGIN
FOR temprow IN
SELECT * FROM your_schema.your_list WHERE list_id = NEW.list_id ORDER BY rank ASC
LOOP
UPDATE your_schema.your_list SET rank = row_idx * 100 WHERE id = temprow.id;
row_idx := row_idx + 1;
END LOOP;
RETURN NEW;
END;
$re_rank_list$ LANGUAGE plpgsql;
CREATE TRIGGER re_rank_list AFTER UPDATE ON your_schema.your_list_value
FOR EACH ROW
WHEN (pg_trigger_depth() = 0)
EXECUTE PROCEDURE re_rank_list();
Pro můj případ použití není výkon znepokojivý, ale důvěra v to, že se nikdy nezlomí nebo nebude chovat podivně, je důležitá.