sql >> Databáze >  >> RDS >> PostgreSQL

Jak udržovat data netříděná?

Nejdůležitější věcí k pochopení je, že tabulky SQL nemají uspořádání . Pořadí řádků, které vidíte, když SELECT bez ORDER BY pouze zůstává stejný, protože je pro databázi rychlejší, než je dostane v tomto pořadí, než v jiném pořadí. PostgreSQL vrátí řádky pouze v tomto pořadí, když provedete sekvenční skenování tabulky; pokud může pro dotaz použít index, pak obvykle získáte řádky v jiném pořadí.

Tato odpověď, kterou jsem napsal dříve, může být pro vás informativní.

V PostgreSQL UPDATE s na řádky je mohou přesunout na jiné místo v tabulce a změnit pořadí, ve kterém jsou vráceny. Stejně tak proces autovakuování na pozadí a různé další operace jako VACUUM a CLUSTER .

Takže musíte nikdy spolehnout se na „výchozí“ objednání čehokoli. Pokud chcete řádkům dát nějaký druh pořadí, musí mít klíč, na kterém je můžete třídit.

Pokud jste vytvořili tabulku bez klíče a nyní si uvědomujete, že by jej měla mít, můžete se ze situace dostat pomocí ctid systémový sloupec. Ne spolehnout se na to pro produkční použití, je to interní sloupec systému, který je viditelný pro uživatele pouze pro účely nouzové obnovy a diagnostiky. Nejprve zjistěte, zda je fyzické uspořádání na disku skutečně požadované pořadí:

SELECT row_number() OVER () AS mytable_id, *
FROM mytable
ORDER BY ctid;

Pokud ano, můžete přidat nový sloupec klíče, který je předem nastaven na automaticky inkrementovaný klíč aplikovaný v pořadí řádků na disku. Toho lze dosáhnout dvěma způsoby. Nejbezpečnější je:

BEGIN;
LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE;
ALTER TABLE mytable RENAME TO mytable_old;

CREATE TABLE mytable (id SERIAL PRIMARY KEY, LIKE mytable_old INCLUDING ALL);

INSERT INTO mytable
SELECT row_number() OVER () AS id, *
FROM mytable_old
ORDER BY ctid;

SELECT setval('mytable_id_seq', (SELECT max(id)+1 FROM mytable));

COMMIT;

až si budete jisti, že jste s výsledky spokojeni, DROP TABLE mytable_old; . Podívejte se na toto demo:http://sqlfiddle.com/#!12/2cb99/2

Rychlý a snadný, ale méně bezpečný způsob je jednoduše vytvořit sloupec a spolehnout se na to, že PostgreSQL přepíše tabulku od začátku do konce:

ALTER TABLE mytable ADD COLUMN mytable_id SERIAL PRIMARY KEY;

Neexistuje absolutně žádná záruka že PostgreSQL bude přidělovat ID v pořadí, i když v praxi to tak bude. Podívejte se na ukázku SQLFiddle.

Uvědomte si, že když použijete SEQUENCE (což je SERIAL sloupec vytvoří) existuje několik chování, které byste možná nečekali. Když vkládáte více řádků najednou, řádkům nemusí být nutně přiřazena ID v přesném pořadí, v jakém od nich očekáváte, a mohou se „objevit“ (stanou se viditelnými) v jiném pořadí, než v jakém jim byla přiřazena ID a vložena. Pokud se transakce vrátí zpět, vygenerované ID bude navždy zahozeno, takže v číslování vzniknou mezery. To je velmi dobré, pokud chcete, aby databáze byla rychlá, ale není to ideální, pokud chcete číslování bez mezer. Pokud je to to, co potřebujete, vyhledejte „postgresql gapless sequence“.



  1. Skalární funkce ODBC pro datum a čas na serveru SQL (příklady T-SQL)

  2. Funkce MariaDB JSON

  3. Prehistorický a moderní přístup k návrhovým databázím

  4. Počítání počtu výskytů podřetězce v řetězci v PostgreSQL