web-dev-qa-db-fra.com

Utilisation d'index sur une table temporaire

J'ai deux questions assez simples. La première requête

 UPDATE mp_physical SET periodic_number = '' WHERE periodic_number is NULL;

et c'est plan

 duration: 0.125 ms  plan:
    Query Text: UPDATE mp_physical  SET periodic_number = '' WHERE periodic_number is NULL;
    Update on mp_physical  (cost=0.42..7.34 rows=1 width=801)
      ->  Index Scan using "_I_periodic_number" on mp_physical  (cost=0.42..7.34 rows=1 width=801)
            Index Cond: (periodic_number IS NULL)

Et le second:

 UPDATE observations_optical_temp SET designation = '' WHERE periodic_number is NULL;

et c'est plan:

duration: 2817.375 ms  plan:
    Query Text: UPDATE observations_optical_temp SET periodic_number = '' WHERE periodic_number is NULL;
    Update on observations_optical_temp  (cost=103.55..9223.01 rows=5049 width=212)
      ->  Bitmap Heap Scan on observations_optical_temp  (cost=103.55..9223.01 rows=5049 width=212)
            Recheck Cond: (periodic_number IS NULL)
            ->  Bitmap Index Scan on "_I_per_num_temp"  (cost=0.00..102.29 rows=5049 width=0)
                  Index Cond: (periodic_number IS NULL)

Je m'attends à ce que le deuxième plan shold soit le même le premier. Mais ce n'est pas. Pourquoi? Voici des décharges des tables.

CREATE TABLE public.mp_physical(
    id_mpp serial NOT NULL,
    id_comet_parts integer,
    "SPK_id" public.nonnegative_int,
    designation varchar(30),
    name varchar(100),
    prefix varchar,
    "is_NEO" bool,
    "H" double precision,
    "G" double precision,
    diameter public.nonnegative_double,
    extent varchar(30),
    extent_error public.nonnegative_double,
    geometric_albedo public.nonnegative_double,
    rot_per public.nonnegative_double,
    "GM" public.nonnegative_double,
    "BV" public.nonnegative_double,
    "UB" public.nonnegative_double,
    "spec_B" varchar(30),
    "spec_T" varchar(30),
    lca double precision,
    multiplicity public.nonnegative_int,
    polar_ang double precision,
    polar_slope_ang double precision,
    a double precision,
    b double precision,
    mass public.nonnegative_double,
    mp_type public.mp_type NOT NULL,
    periodic_number varchar(5),
    diameter_method_def varchar(200),
    discovery_info text,
    "H_sigma" public.nonnegative_double,
    "G_sigma" public.nonnegative_double,
    diameter_sigma public.nonnegative_double,
    geometric_albedo_sigma public.nonnegative_double,
    rot_per_sigma public.nonnegative_double,
    "GM_sigma" public.nonnegative_double,
    "BV_sigma" public.nonnegative_double,
    "UB_sigma" public.nonnegative_double,
    lca_sigma public.nonnegative_double,
    a_sigma public.nonnegative_double,
    b_sigma public.nonnegative_double,
    polar_ang_sigma public.nonnegative_double,
    mass_sigma public.nonnegative_double,
    CONSTRAINT "_C_id_ap" PRIMARY KEY (id_mpp)
);

CREATE INDEX "_I_name" ON  mp_physical  USING btree (name);
CREATE INDEX "_I_designation" ON mp_physical USING btree(mpp_designation);
CREATE INDEX "_I_periodic_number" ON mp_physical USING btree(periodic_number);
CREATE INDEX "_I_mp_type" ON mp_physical USING btree(mp_type);

Et

  CREATE TEMPORARY TABLE "observations_optical_temp"(note_1,date,"RA","Dec",magnitude,band,id_observatory,id_mpp,"Dec_degree",observatory_code,periodic_number,mpp_designation,mp_type)
AS SELECT note_1,date,"RA","Dec",magnitude,band,id_observatory,id_mpp,"Dec_degree",'1'::varchar(3),'1'::varchar(8),'1'::varchar(30),'A'::public.mp_type FROM observations_optical;

CREATE TABLE observations_optical(
    id_obs_o bigint
    note_1 varchar,
    date timestamp NOT NULL,
    "RA" time NOT NULL,
    "Dec_degree" integer NOT NULL,
    "Dec" time NOT NULL,
    magnitude double precision,
    band varchar,
    id_observatory integer,
    id_mpp integer,
    CONSTRAINT "_PK_id_obs_o" PRIMARY KEY (id_obs_o)
);
CREATE INDEX "_I_temp_1" ON observations_optical_temp USING btree(mpp_designation);
CREATE INDEX "_I_temp_2" ON observations_optical_temp USING btree(periodic_number);
CREATE INDEX "_I_temp_3" ON observations_optical_temp USING btree(mp_type);
4
Artem Zefirov

Le choix entre l'analyse de l'index et l'analyse de l'indice bitmap est essentiellement décidé par le nombre de lignes par page de données Postgres prévoit de récupérer - ce qui dépend des statistiques sur la distribution des données dans le tableau et la sélectivité de vos prédicats de requête.

Si Postgree s'attend à trouver plusieurs lignes sur la même page de données, elle bascule vers l'analyse d'index bitmap, ce qui est plus efficace pour ce type de distribution de données physiques. (Et si la plupart des pages de données sont récupérées de toute façon, une analyse très séquentielle est plus rapide.) Donc, même si les colonnes et les index de vos deux tables se ressemblent, vous pouvez toujours obtenir ces différents plans de requête en fonction de la distribution de données et de la sélectivité de votre requête. prédicats.

Mais vos tables sont très différentes de commencer. mp_physical a beaucoup de lignes plus larges, de sorte que seulement peu de lignes sont situées sur la même page de données (8kb par défaut). Cet indice fortement favorable scanne, car les analyses d'index bitmap n'achètent pas beaucoup (si quelque chose) même lors de la récupération d'un pourcentage plus élevé de toutes les lignes.

Aussi, soyez conscient que Les tables temporaires ne sont pas couvertes par autovacuum et ne sont donc pas analysés automatiquement. Vous devrez peut-être le faire manuellement pour obtenir des statistiques de table précises pour le planificateur de requêtes pour travailler avec:

ANALYZE observations_optical_temp;
4
Erwin Brandstetter