Fix tsmatchsel() to account properly for null rows.
authorTom Lane
Fri, 18 Feb 2011 00:00:54 +0000 (19:00 -0500)
committerTom Lane
Fri, 18 Feb 2011 00:00:54 +0000 (19:00 -0500)
ts_typanalyze.c computes MCE statistics as fractions of the non-null rows,
which seems fairly reasonable, and anyway changing it in released versions
wouldn't be a good idea.  But then ts_selfuncs.c has to account for that.
Failure to do so results in overestimates in columns with a significant
fraction of null documents.  Back-patch to 8.4 where this stuff was
introduced.

Jesper Krogh

src/backend/tsearch/ts_selfuncs.c
src/include/catalog/pg_statistic.h

index e7194ce66e272bde2b2967f6299df5be6ec16c71..b679b7544a300303255ef57e2c097f2665c1fb4f 100644 (file)
@@ -189,11 +189,17 @@ tsquerysel(VariableStatData *vardata, Datum constval)
            /* No most-common-elements info, so do without */
            selec = tsquery_opr_selec_no_stats(query);
        }
+
+       /*
+        * MCE stats count only non-null rows, so adjust for null rows.
+        */
+       selec *= (1.0 - stats->stanullfrac);
    }
    else
    {
        /* No stats at all, so do without */
        selec = tsquery_opr_selec_no_stats(query);
+       /* we assume no nulls here, so no stanullfrac correction */
    }
 
    return selec;
index 797774339d1a7e382af735e2960ed3a2c60abb15..f5965b56ec63239e99001b610103aac6a93095fd 100644 (file)
@@ -246,6 +246,8 @@ typedef FormData_pg_statistic *Form_pg_statistic;
  * type with identifiable elements (for instance, tsvector).  staop contains
  * the equality operator appropriate to the element type.  stavalues contains
  * the most common element values, and stanumbers their frequencies.  Unlike
+ * MCV slots, frequencies are measured as the fraction of non-null rows the
+ * element value appears in, not the frequency of all rows.  Also unlike
  * MCV slots, the values are sorted into order (to support binary search
  * for a particular value).  Since this puts the minimum and maximum
  * frequencies at unpredictable spots in stanumbers, there are two extra