Hallo TS,
Ich möchte nur deinen Gedankengang verstehen und auch herausfinden, wieso die Bewertung der Frage scheinbar unabhängig von den Randbedingungen stattfinden kann.
Weil die Frage nicht war „warum wird bei dieser Query der Index nicht benutzt“ sondern „wie kommt das RDBMS zu der Entscheidung, einen Index nicht zu nutzen.“ Da die Entscheidung, ob ein Index benutzt wird oder nicht, auf einem Algorithmus basiert, kann auch ohne Kenntnis einer konkreten Query der Entscheidungsbaum, auf dem diese Entscheidung basiert, beschrieben werden.
Du selber schreibst doch nun hier einige Wenns und Abers. Die Reaktion des Optimizers hängt also augenscheinlich doch von Bedingungen ab.
Selbstverständlich hängt er von Bedingungen ab. Und die Frage war, welche Bedingungen das sind.
Soweit kann ich das nachvollziehen. Allerdings: woher soll das DBMS wissen, ob ein Ergebnis zu groß werden wird.
Statistik. Reine Statistik, basierend auf den Metadaten, die das RDBMS über die Daten sammelt.
Selbst bei einer so vagen Abfrage "... WHERE <SPALTE> LIKE 'Sch%'" muss das Ergebnis nicht groß werden und erfahrungsgemäß wird hier auch ein Index benutzt, falls er auf <SPALTE> existiert.
Das dürfte sehr stark vom DBMS und der Qualität der Statistiken sowie der abgeschätzten Größe des Resultsets abhängen. PostgreSQL etwa hat Statistiken über die Kardinalität eines Index, sowie Statistiken basierend auf Histogrammen, usw. Mal ein Beispiel auf Basis der Foren-Datenbank:
> explain select message_id from messages where message_id = 10;
QUERY PLAN
-----------------------------------------------------------------------------------
Index Only Scan using messages_pkey on messages (cost=0.43..2.65 rows=1 width=8)
Index Cond: (message_id = 10)
(2 Zeilen)
Das rows=1
sagt dir, dass PostgreSQL hier eine Zeile vermutet. Kunststück bei einem primary key ;-) und dementsprechend wird auch der Index verwendet.
> explain select message_id from messages where message_id > 10;
QUERY PLAN
-------------------------------------------------------------------
Seq Scan on messages (cost=0.00..206608.54 rows=1728194 width=8)
Filter: (message_id > 10)
(2 Zeilen)
PostgreSQL sagt dir hier mit rows=1728194
, dass es 1.728.194 Zeilen erwartet und dementsprechend der Index keinen Sinn macht.
cforum_development=# explain select message_id from messages where message_id > 1728060;
QUERY PLAN
-----------------------------------------------------------------------------------
Index Only Scan using messages_pkey on messages (cost=0.43..3.74 rows=2 width=8)
Index Cond: (message_id > 1728060)
(2 Zeilen)
Hier sagt PostgreSQL dir, dass es 2 rows erwartet und dementsprechend der Index benutzt wird.
Das nur soweit, dass Du verstehst, warum ich auf Nennung des Querys plädiere.
Nur dass nicht nach der Optimierung einer Query gefragt wurde, sondern nach dem Entscheidungsbaum eines Algorithmus.
Plakatives Beispiel: wenn du aber von den 128gb bei einer Abfrage 100gb der Rows zurück bekommen würdest, wird kein sinnvolles DBMS der Welt den Index verwenden.
Wie stellt es fest, dass die Treffermenge so hoch sein wird (siehe auch oben)?
Siehe oben. Über Statistik.
Oder wird es mitten in der Ausführung der Abfrage die Strategie umstellen von Indexnutzung auf sequentiellen Scan, wenn z. B. jede zweite Row einen Treffer liefert?
Nein. Ich wüsste jetzt auch nicht, wie man das implementieren sollte.
Bei Index-Bäumen gibt es da ja auch immer noch das Problem der Nicht-Balanciertheit...
Das ist ein völlig anderes Themengebiet. tl;dr-Version: um das zu vermeiden, wird idR ein Reindex bzw. optimize in regelmäßigen Intervallen ausgeführt. Das allerdings nicht von dem DBMS selber.
LG,
CK