【问题标题】:Multi Column Indexes with Order By and OR clause具有 Order By 和 OR 子句的多列索引
【发布时间】:2021-10-13 03:12:08
【问题描述】:

我有以下查询来获取门票列表。

EXPLAIN select * from ticket_type
                where ticket_type.event_id='89898'
                and ticket_type.active=true
                and (ticket_type.is_unlimited = true OR ticket_type.number_of_sold_tickets < ticket_type.number_of_tickets)
                order by ticket_type.ticket_type_order

我在下面创建了索引但没有工作。

  1. 索引 (ticket_type_order,event_id,is_unlimited,active)
  2. 索引 (ticket_type_order,event_id,active,number_of_sold_tickets,number_of_tickets)。

【问题讨论】:

  • 如果有的话,ticket_type_order 需要排在最后,以便 Postgres 可以遍历 where 条件上的索引,然后以正确的顺序获取行。 number_of_sold_tickets &lt; number_of_tickets 不过会很困难,我怀疑那是可索引的

标签: postgresql indexing


【解决方案1】:

这个查询的完美索引应该是

CREATE INDEX ON ticket_type (event_id, ticket_type_order)
   WHERE active AND (is_unlimited OR number_of_sold_tickets < number_of_tickets);

当然,像这样的部分索引可能只对这个特定的查询有用。

如果索引定义中的WHERE 条件不是很有选择性,或者执行速度稍慢也是可以接受的,您可以省略部分或整个WHERE 子句。这使得索引更广泛地有用。

【讨论】:

    【解决方案2】:

    表的大小和通常的查询结果是多少?如果服务器期望返回超过一半的表,服务器通常足够智能并禁用索引。

    索引没有意义,如果结果相当小。如果服务器在几个过滤步骤后有 - 比方说 - 1000 条记录,则服务器停止使用索引。使用 CPU 完成查询,然后从 HDD 加载索引更便宜。因此,索引永远不会应用于小表。

    Order by 在查询处理的最后应用。索引中的第一个字段应该是来自where 过滤器的字段之一。

    布尔字段在索引中很少有用。它只有两个可能的值。应该为具有许多不同值的字段创建索引。

    避免or 过滤。在你的情况下很容易。如果门票无限,请在number_of_tickets 中输入一个非常大的数字。

    在您的情况下,更好的索引将只是 event_id。如果数据库服务器支持功能索引,那么可以尝试添加number_of_tickets - number_of_sold_tickets。将语句改写为where number_of_tickets - number_of_sold_tickets &gt; 0

    更新:Postgresql 称之为“表达式索引”:

    https://www.postgresql.org/docs/current/indexes-expressional.html

    【讨论】:

      猜你喜欢
      • 2021-07-06
      • 2013-01-09
      • 2021-07-20
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 2014-11-20
      • 1970-01-01
      相关资源
      最近更新 更多