3

我运行一个使用 PostgreSQL 9.1 作为后端的食谱网站。当用户搜索食谱时,我会根据用户想要查找的内容即时构建查询。例如,如果用户想要查找烹饪时间低于 30 分钟的所有食谱,我将生成查询:

SELECT * From Recipes WHERE CookTime < 30;

我现在需要“隐藏”某些食谱,这意味着它们永远不会出现在任何搜索中。找到他们的唯一方法是直接知道 URL。为此,我在 Recipes 表中添加了一个新列:

ALTER TABLE Recipes ADD COLUMN Hidden boolean not null default false;
CREATE INDEX IDX_Recipes_Hidden ON Recipes(Hidden);

我的想法是将短语“NOT HIDDEN”硬编码到每个 WHERE 子句中。例如,上面的查询现在是:

select * from recipes where not Hidden and CookTime < 30;

我的问题:

根据查询分析器,这将生成一个位图来组合两个索引。请记住,99% 的食谱不会被隐藏。我想知道这种技术是否是从所有查询中排除某些食谱的最佳、最快的方法。我知道绝对最快的方法是为隐藏的食谱创建一个单独的表,但是这将是大量的重构,所以我想避免这种情况。

4

3 回答 3

2

你有任何性能问题吗?如果您的解决方案没有问题,那么在不需要更改的事情上浪费更多时间是没有意义的。

位图索引适用于您没有很多不同值的情况。因此,在您只有真假的情况下,这很好。

您可以只构建一个物化视图之类的东西,但这似乎需要做很多工作,而且您可能更容易创建第二个表,但如果您没有任何问题,请不要更改任何内容。

postgres 中的 MV:http: //tech.jonathangardner.net/wiki/PostgreSQL/Materialized_Views

于 2012-04-19T04:27:48.837 回答
1

阻止行再次出现的最快方法是......删除它们。

但是,如果您出于某种目的希望它们四舍五入,但不希望它们用于几乎所有查询,您可以重命名表并在其位置创建一个新视图。

ALTER TABLE Recipes RENAME TO AllRecipes;
ALTER TABLE AllRecipes ADD Hidden BOOLEAN NOT NULL DEFAULT FALSE;
CREATE VIEW Recipes AS SELECT * FROM AllRecipes WHERE NOT Hidden;

就您需要重写多少代码而言,这是最快的(假设您在 Recipies 上的应用程序上有很多查询,并希望所有查询都排除隐藏的)。

但它也为您提供了简单的选项,使其也能快速提高性能。首先,您可以在 Hidden 上添加索引。但您也可以将其划分为两个子表,VisibleRecipes 和 HiddenRecipies。视图食谱将准确显示 VisibleRecipies 中的食谱。

但是表 AllRecipies 可以是具有 VisibleRecipes 和 HiddenRecipes 作为其分区的父表,也可以是视图本身。

于 2012-04-19T05:59:52.453 回答
0

如果你没有性能问题是可以的。

如果我是引擎,我会使用索引来获取 CookTime 小于 30 的表行,然后我会过滤隐藏 = true 的行。如果您知道如何执行此操作(仅使用烹饪时间索引),则可以对其进行测试。

但是,如果您的分析仪更快地发现使用两个索引...

确保您有关于收集的表和索引的统计信息。(我有 Oracle 方面的专业知识,而不是 Postgres)

于 2012-04-19T05:42:55.567 回答