【问题标题】:Ordering by average rating - how to speed it up?按平均评分排序 - 如何加快速度?
【发布时间】:2015-04-24 13:45:42
【问题描述】:

我在一个表中有两列:

rating_total integer
rating_count integer

rating_total 是总评分的总和,评分计数是总评分的数量。我想按平均价格订购:

ORDER BY (rating_total/rating_count) DESC, id ASC

我应该为average_rate 创建单独的列吗?或者可以创建一些索引来加快速度?


我已经设法创建这样的索引:

CREATE INDEX "posts-avg-rating-index" 
ON "Posts" (("rating_total"::float/(CASE "rating_count" WHEN 0 THEN NULL ELSE "rating_count" END)) DESC NULLS LAST, id DESC);'

这适用于这样的订购:

ORDER BY (("rating_total"::float/(CASE "rating_count" WHEN 0 THEN NULL ELSE "rating_count" END)) DESC NULLS LAST, id DESC)

【问题讨论】:

  • 您应该使用单独的column 或在此答案上使用look
  • 您是否尝试在( (rating_total/rating_count), id ) 上创建索引?您还应该阅读以下内容:stackoverflow.com/tags/postgresql-performance/info 并添加缺失的信息。
  • 很可能不,您可能应该在索引定义中使用与 order by 子句中相同的表达式,然后它肯定会起作用。
  • 你真的应该避免引用标识符。从长远来看,它们带来的麻烦远多于它们的价值。
  • PostgreSQL 中的列名应始终小写,下划线用作单词/标记分隔符。其他任何事情都只是要求痛苦。仅仅因为您的数据源是来自 REST API 的 JSON,这并不意味着数据库中的列名必须遵循与 JSON 响应中的键相同的命名约定。

标签: sql postgresql indexing sql-order-by postgresql-9.3


【解决方案1】:

您的问题造成了一些混乱,因为“平均评分”通常是跨多行计算的值,无法编入索引。

在您的情况下,您显然希望按相同行中两列的商排序,这恰好是“总数”和“计数”。对于这种情况,您当然可以拥有expression index - 您自己已经找到了。

您可以使用NULLIF 进行简化:

CREATE INDEX posts_avg_rating_index
ON "Posts" (cast(rating_total AS float)/NULLIF(rating_count, 0) DESC NULLS LAST, id DESC);

在查询中使用相同的表达式。

关于cast()速记语法name::type和表达式索引:

宁可使用合法名称。标识符中的破折号 (-) 在双引号中是合法的,但只是自找麻烦。

【讨论】:

  • 是否有令人信服的理由在物化视图和索引或 [trigger updated] 计算值列上使用表达式索引?似乎表达式索引无论如何都需要在内部存储结果..
  • @user2864740:这是个好问题。这两种解决方案都有其自身的成本、收益和副作用。请为此提出一个新的问题。评论不是地方。您可以随时链接到此问题以获取上下文。
猜你喜欢
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多