20. september 2001 - 11:40Der er
18 kommentarer og 1 løsning
Explain/Optimering
PostgreSQL har desværre en kedelig bagside - den styrre ikke rigtig brugen af indexes m.m. Men hvor om alt er, så skal jeg altså bruge postgreSQL og må derfor finde en løsning.
Se på følgende tabeller:
CREATE TABLE \"folder2\" ( \"id\" int4 NOT NULL, \"title\" character varying(255) NOT NULL, \"keywords\" character varying(255), \"description\" text, \"sort_by\" character varying(10) NOT NULL, \"folder_type\" character varying(10), Constraint \"folder_pkey\" Primary Key (\"id\") );
CREATE TABLE \"objects2\" ( \"num_id\" int4 DEFAULT nextval(\'objects_num_id_seq\') NOT NULL, \"id\" int4 NOT NULL, \"parent\" character varying(40) NOT NULL, \"site_id\" character varying(40) NOT NULL, \"type\" character varying(20) NOT NULL, \"sort_order\" int4 NOT NULL, \"date_updated\" timestamp with time zone NOT NULL, \"user_id\" character varying(40) NOT NULL, \"status\" int2 DEFAULT 1 NOT NULL, Constraint \"objects_pkey\" Primary Key (\"id\") ); create index objects_status_index on objects2(status);
Og se så hvad der sker...
explain select t1.id, t1.sort_by from folder t1, objects t2 where t1.id = t2.id and status = int2(1) or status = int2(0) and sort_by <> \'manual\' ;
Nested Loop (cost=0.00..55276.84 rows=23425 width=38) -> Index Scan using objects_status_index, objects_status_index on objects t2 (cost=0.00..1241.48 rows=1201 width=14) -> Seq Scan on folder t1 (cost=0.00..20.00 rows=1000 width=24)
Den laver en Seq scan på folder2 tabellen selv om der er index på id! Det sjove er så, at fjerner jeg status sammenligningen, så benytter den index\'et på folder2 tabellen - total trist at det er sådan.
Bemærk iøvrigt hvordan det er nødvendigt at typecaste for at få den til at benytte index på status kolonnen...
Den moderne arbejdsplads er i stigende grad afhængig af mødelokaler til at fremme samarbejde, men dette skift medfører også stigende sikkerhedsudfordringer.
pgsql bruger for det første automatisk oid\'s - prøv at skrive
SELECT oid,* FROM <et-eller-andet-table>
De er unikke for hver enkelt row i hele databasen - brug dog dem?
der er iøvrigt noget meget uheldigt ved din konstruktion - \'Rule of left indexing\' - dvs, at indekserede kolonner skal holdes til venstre, og ordnet efter hvor tit du vælger ud fra dem - eksempel:
hvis man har et fodboldhold,
spiller_id (unik key), troeje_nr (indekseret), cpr_nr (indekseret), navn
vil man kunne drage nytte af alle tre indexes hvis man vælger f.eks.
- så kan kun index på spiller_id benyttes, fordi man har en ikke indekseret kolonne i midten.. derfor er det en ide at indeksere de kolonner der er længst til venstre.
Derudover er det vigtigt, at indeksere kolonner der har mange værdier - hvis status for eksempel har 3-4 mulige værdier, skal databasen jo stadig trawle gennem 1/# - 1/4 af databasen..
Alt hvad ud skriver har jeg alerede styr på - men tillad mig lige at uddybe nu da du har skrevet så meget:
oid kan jeg ikke bruge til meget, da jeg er nød til at havde styr på id\'erne - de skal jo bruges til at samle flere tabeller!!! Så oid på den ene tabel er ikke at finde i den anden!
Rækkefølgen af index\'es er også klar nok - men heller ikke lige det der burde give mig problemer jvf. mit eks.
Og ja - der ER jo index på status, da denne kan antage værdierne 0,1,10 og 11.
Men ellers tak for svaret - det hjælper mig sog desværre ikke meget videre...;-(
PT er det ikke foreign keys - men de binder tabellerne sammen. Der er en objekt tabel med id numre, som referere til andre tabeller via. denne entydige nøgle (id).
På sigt skal de naturligvis laves til foreign keys - men det er ikke noget der sker idag eller imorgen.
CREATE TABLE vare( fabrik_id OID, firma_id OID, retailer_id OID, serial_number varchar(64), title varchar(128), description text );
hvor firma_id (OID) refererer til det indbyggede OID på firmas tabellen. Ligesom dig skal jeg på sigt have lavet foreign keys formelt, men det her virker ganske fint for nu, og er for så vidt ikke anderledes end de indexes jeg plejer at bruge i mysql..
Det er jo fint nok - men jeg er nød til at holde mig til laveste fællesnævner. Alt hvad jeg laver SKAL kunne køre på MySQL, postgreSQL, Oracle og MSQL - og hvad der ellers måtte være. Jeg har lavet det fede database abstraktionslag - så det spiller bare...
He he - det er selvfølgelig rigtigt nok; men aligevel! Mit problem oven for med id kolonnen som primary key burde virke og postgres burde bruge det index der automatisk oprettes...
Jeg er lige faldet over nogel interessante ting i dokumentationen omkring explain, som jeg har meget spas med selv, det virker som om query-optimizer/planner aben træffer beslutningen om, hvorvidt der skal bruges sequential eller index scan, ud fra nogle obskure kriterier..
Du kan læse mere om den, og om hvordan man evt. kan tilsidesætte dens snedige regler på
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.