我运行一个使用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);
我的想法是在每个WHERE子句中硬编码“NOT HIDDEN”这个短语。例如,上面的查询现在是:
select * from recipes where not Hidden and CookTime < 30;
我的问题:
根据查询分析器,现在将生成一个位图来组合这两个索引。请记住,99%的食谱将不隐藏。我想知道这种技术是否是从所有查询中排除某些食谱的最佳方法。我知道绝对最快的方法是为隐藏的食谱创建一个单独的表,但这将是一个大量的重新分解,所以我想避免这种情况。
答案 0 :(得分:2)
您有任何性能问题吗?如果您的解决方案没有问题,那么将更多时间浪费在不需要改变的事情上是没有意义的。
对于没有多少不同值的内容,位图索引很适合。因此,在您只有真假的情况下,这很好。
你可以构建类似于物化视图的东西,但这看起来很多工作,你可能更容易创建第二个表,但如果你没有任何问题,不要改变任何东西。 / p>
postgres中的MV:http://tech.jonathangardner.net/wiki/PostgreSQL/Materialized_Views
答案 1 :(得分: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上有很多查询,并且希望所有代码都排除隐藏的代码)。
但它也为您提供了简便的选择,使其快速提升性能。首先,您可以在隐藏上添加索引。但您也可以将其分为两个子表,VisibleRecipes和HiddenRecipies。视图Recipes将显示VisibleRecipies中的视图。
但是AllRecipies表可以是一个以VisibleRecipes和HiddenRecipes作为其分区的父表,也可以是一个视图本身。
答案 2 :(得分:0)
如果您没有性能问题,那就没关系。
如果我是引擎,我会使用索引来获取CookTime小于30的表行,然后我会过滤那些hidden = true的表。 如果您知道如何强制执行此操作(仅使用cooktime索引),则可以对其进行测试。
但是如果您的分析仪更快地找到两个索引的使用......
确保您收集了有关表和索引的统计信息。 (我有Oracle的专业知识,而不是Postgres)