Vous n'êtes pas identifié(e).

#1 Re : PL/pgSQL » [RESOLU]Non utilisation d'index sur un LIKE en pl/pgsql » 08/01/2014 09:15:00

Merci pour cette réponse très claire.

Voila donc la transformation du code qui fonctionne :

DO $$
DECLARE
    y record;
    x record;
BEGIN
FOR y IN (
    SELECT id,chaine
    FROM matable
    WHERE id < 1000
    ) LOOP
      
    FOR x IN EXECUTE concat ('SELECT count(1) nb'
                            ,' FROM matable m' 
                            ,' WHERE m.chaine LIKE ',quote_literal(y.chaine)
                            ,' AND m.id <> ',y.id
                            )
    LOOP
        RAISE INFO '%-%-%',y.id,y.chaine,x.nb;
    END LOOP;
END LOOP;
END$$;

A noter qu'il faut impérativement ne pas mettre de parenthèses dans "FOR x IN EXECUTE" (autrement dit FOR x IN (EXECUTE...) ne fonctionne pas, alors que FOR x IN (SELECT ...) fonctionne).

#2 PL/pgSQL » [RESOLU]Non utilisation d'index sur un LIKE en pl/pgsql » 07/01/2014 17:37:32

ladeche
Réponses : 3

Bonjour,

Soit une bête table avec une clef primaire et un champ varchar indexé :

CREATE TABLE matable
(
  id integer NOT NULL,
  chaine character varying,
  CONSTRAINT pk_id PRIMARY KEY (id )
) WITH (  OIDS=FALSE);
CREATE INDEX idx_chaine  ON matable  USING btree   (chaine COLLATE pg_catalog."default" );

Si je fais

 
SELECT * FROM matable where chaine = '000ZX34/14'; 
SELECT * FROM matable where chaine LIKE '000ZX34/14' ;

Dans les deux cas l'optimiseur utilise l'index idx_chaine.

Par contre si je fais le script suivant :

DO $$
DECLARE
    y record;
    x record;
BEGIN
FOR y IN (
    SELECT id,chaine
    FROM matable
    WHERE id < 200
    ) LOOP
    FOR x IN (SELECT count(1) nb
                 FROM matable m
                 WHERE m.chaine LIKE y.chaine
                 AND m.id <> y.id
                 )
       LOOP                                                             
        RAISE INFO '%-%-%',y.id,y.chaine,x.nb;
       END LOOP;
END LOOP;
END$$;

L'index ne sera pas utilisé dans la requête imbriquée (FOR x), à la place on a un seq scan. En remplaçant le like par =, l'index est utilisé.
J'ai essayé en ajoutant un index sur chaine avec la classe opérateur "varchar_pattern_ops" mais sans plus de succès.

Le bout de code ci-dessus est un peu idiot mais je voudrais surtout comprendre le fonctionnement du LIKE dans ce cas là et pourquoi il n'utilise pas l'index.

Merci.

Pied de page des forums

Propulsé par FluxBB