Ich fürchte, meine Frage ist alt:
Der Query
SELECT id,hostname FROM names WHERE domain_id=1 AND ipcount>0 LIMIT 1000;
verwendet keinen Index und ist entsprechend langsam.
Die Tabelle besteht im wesentlichen aus
Table names
id (serial)
hostname (varchar)
domain_id (integer, not null, default=0)
tld_id (integer, not null, default=0)
ipcount (integer, not null, default=0);
Auf allen Spalten liegt je ein Index, es gibt rund 40 Millionen Einträge, derzeit rund 5 Millionen (über die Tabelle verteilt), auf die obige Bedingung zutrifft. Wie oben beschrieben dauert der Query bis zu einigen Minuten…
Postgresql weigert sich standhaft, einen (oder zwei) index(e) für domain_id und ipcount zu verwenden. Schränke ich die Bedingung auf ein Feld ein, wird ein Index verwendet.
Ich habe einen kombinierten Index (domain_id, ipcount) versucht, ebenfalls ohne Erfolg.
Ich habe den Query geändert (geklammert) - ohne Erfolg.
PG (8.1.2) sagt:
EXPLAIN SELECT id,hostname FROM names WHERE domain_id=1 AND ipcount>0;
QUERY PLAN
Seq Scan on “names” (cost=0.00…1045608.23 rows=6547054 width=27)
Filter: ((domain_id = 1) AND (ipcount > 0))
(2 Zeilen)
Alles was mir jetzt noch einfällt, wäre, das in einen Subquery zu kapseln, damit pro Query nur ein Index verwendet wird - aber das wäre dann ja wie bei MySQL.
Setze ich ein “ORDER BY ID” dran, wird der entsprechende Index verwendet.
Setze ich ein “ORDER BY ipcount,domain_id” dran, bleibt es wiederrum ein sequential scan.
Ich bin mit meinem Latein am Ende.
[edit]
Falls das hilft:
domains=# SELECT relname, relkind, reltuples, relpages FROM pg_class WHERE relname LIKE ‘names%’;
relname | relkind | reltuples | relpages
---------------±--------±------------±---------
names_id_seq | S | 1 | 1
names_ipcount | i | 4.17133e+07 | 95689
names | r | 4.16982e+07 | 419141
names_tld_id | i | 4.17177e+07 | 95738
names_pkey | i | 4.17113e+07 | 96908
(5 Zeilen)
Sehr verwunderlich finde ich dies:
domains=# SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = ‘names’;
attname | n_distinct | most_common_vals
------------±-----------±---------------------------------------------------------------------------------------------------------
id | -1 |
hostname | -1 |
ipcount | 12 | {1,0}
lastupdate | 52434 | {111,1156607575,1156611410,1156626237,1156640686,1156645606,1156658560,1156668110,1156674849,1156681689}
tld_id | 34 | {0}
domain_id | 2645 | {1,0,76689,45061,12,1772,113,3959,11670,22073}
(6 Zeilen)
Es gibt definitv nicht 2645 distinct domain_id’s, sondern rund 10.000.000 verschiedene. auch bei den distinct tlds sollte es rund 800 geben, nicht nur 24.
Kann es sein, dass die stats hier den Query-Planer auf eine falsche Fährte locken?
Kann ich das mit “VACUUM ANALYZE” aktualisieren?
Thomas
Thomas