mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-14 08:36:54 +08:00
Improved total cost for cost estimation
This commit is contained in:
40
src/hnsw.c
40
src/hnsw.c
@@ -100,10 +100,8 @@ hnswcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
|
||||
{
|
||||
GenericCosts costs;
|
||||
int m;
|
||||
int entryLevel;
|
||||
int layer0TuplesMax;
|
||||
double layer0Selectivity;
|
||||
double scalingFactor = 0.55;
|
||||
double ratio;
|
||||
double startupPages;
|
||||
double spc_seq_page_cost;
|
||||
Relation index;
|
||||
|
||||
@@ -120,6 +118,8 @@ hnswcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
|
||||
|
||||
MemSet(&costs, 0, sizeof(costs));
|
||||
|
||||
genericcostestimate(root, path, loop_count, &costs);
|
||||
|
||||
index = index_open(path->indexinfo->indexoid, NoLock);
|
||||
HnswGetMetaPageInfo(index, &m, NULL);
|
||||
index_close(index, NoLock);
|
||||
@@ -151,30 +151,38 @@ hnswcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
|
||||
* at L0, accounting for previously visited tuples, multiplied by the
|
||||
* "scalingFactor" (currently hardcoded).
|
||||
*/
|
||||
entryLevel = (int) (log(path->indexinfo->tuples + 1) * HnswGetMl(m));
|
||||
layer0TuplesMax = HnswGetLayerM(m, 0) * hnsw_ef_search;
|
||||
layer0Selectivity = (scalingFactor * log(path->indexinfo->tuples + 1)) /
|
||||
(log(m) * (1 + log(hnsw_ef_search)));
|
||||
if (path->indexinfo->tuples > 0)
|
||||
{
|
||||
double scalingFactor = 0.55;
|
||||
int entryLevel = (int) (log(path->indexinfo->tuples) * HnswGetMl(m));
|
||||
int layer0TuplesMax = HnswGetLayerM(m, 0) * hnsw_ef_search;
|
||||
double layer0Selectivity = scalingFactor * log(path->indexinfo->tuples) / (log(m) * (1 + log(hnsw_ef_search)));
|
||||
|
||||
costs.numIndexTuples = (entryLevel * m) +
|
||||
(layer0TuplesMax * layer0Selectivity);
|
||||
ratio = (entryLevel * m + layer0TuplesMax * layer0Selectivity) / path->indexinfo->tuples;
|
||||
|
||||
genericcostestimate(root, path, loop_count, &costs);
|
||||
if (ratio > 1)
|
||||
ratio = 1;
|
||||
}
|
||||
else
|
||||
ratio = 1;
|
||||
|
||||
get_tablespace_page_costs(path->indexinfo->reltablespace, NULL, &spc_seq_page_cost);
|
||||
|
||||
/* Startup cost is cost before returning the first row */
|
||||
costs.indexStartupCost = costs.indexTotalCost * ratio;
|
||||
|
||||
/* Adjust cost if needed since TOAST not included in seq scan cost */
|
||||
if (costs.numIndexPages > path->indexinfo->rel->pages)
|
||||
startupPages = costs.numIndexPages * ratio;
|
||||
if (startupPages > path->indexinfo->rel->pages && ratio < 0.5)
|
||||
{
|
||||
/* Change all page cost from random to sequential */
|
||||
costs.indexTotalCost -= costs.numIndexPages * (costs.spc_random_page_cost - spc_seq_page_cost);
|
||||
costs.indexStartupCost -= startupPages * (costs.spc_random_page_cost - spc_seq_page_cost);
|
||||
|
||||
/* Remove cost of extra pages */
|
||||
costs.indexTotalCost -= (costs.numIndexPages - path->indexinfo->rel->pages) * spc_seq_page_cost;
|
||||
costs.indexStartupCost -= (startupPages - path->indexinfo->rel->pages) * spc_seq_page_cost;
|
||||
}
|
||||
|
||||
/* Use total cost since most work happens before first tuple is returned */
|
||||
*indexStartupCost = costs.indexTotalCost;
|
||||
*indexStartupCost = costs.indexStartupCost;
|
||||
*indexTotalCost = costs.indexTotalCost;
|
||||
*indexSelectivity = costs.indexSelectivity;
|
||||
*indexCorrelation = costs.indexCorrelation;
|
||||
|
||||
Reference in New Issue
Block a user