【问题标题】:Top 5 unique rows without Distinct from 7Million rows前 5 个唯一行与 700 万行没有区别
【发布时间】:2022-01-06 23:28:21
【问题描述】:

GCP 上的 Postgres 12。 包含大约 700 万行并且还在不断增长的表。

select Distinct col1, col2
from tab_a
where col3='abc'
and col4='xyz'
order by col2
limit 5;

使用 Distinct 此查询大约需要 2.1 到 2.8 秒 没有 Distinct 需要 0.25 秒,但我的表根据业务需求得到了重复数据。

我是否可以在没有昂贵的 Distinct 子句的情况下获得前 5 个唯一记录? 我可以执行以下操作,但它不是可靠的解决方案:

select Distinct 
col1, col2
from (
       select col1, col2
       from tab_a
       where col3='abc'
       and col4='xyz'
       order by col2
       limit 50
     )
limit 5;

有人可以指导我一个更强大的解决方案吗?

愿望

【问题讨论】:

  • 这次在表上有索引还是没有索引。表有索引吗?
  • 首先评论:在您的初始查询中,您限制为 5 个结果行,而仅在 col2 上排序,这意味着您将获得 5 行具有任意 col1 值的行,因为它们没有在 col1 上排序。那么你可以在有和没有DISTINCT 子句的查询上执行EXPLAIN ANALYSE 吗?通常这是代价高昂的ORDER BY 子句。
  • 您没有向我们提供足够的信息来确定时间花在哪里。您还给了我们一个替代版本(尽管正如您所说,它不是一个强大的版本),但没有提到它的速度有多快。选项卡 a 上是否有处理 col3col4 的索引?它是否还包括col2(可能还有col1?)表中有多少行与col3col4 上的WHERE 匹配?这些平均有多少不同的col1col2?等等等等......正如@EdouardH所提到的。 ,请使用 EXPLAIN ANALYZE 运行您的查询,以便我们可以处理。
  • 欢迎来到 Stack Overflow。您使用的用户名与经常回答 SQL 问题的 longtime contributor 相同。也许你最好使用另一个名字。
  • 很抱歉没有提供完整信息@O.Jones 我已经更改了名称(感谢您告诉我)详细信息如下:索引在那里并且查询使用索引。第一个查询解释计划(有不同)ibb.co/DKyj1xn 第一个查询解释计划(没有不同)ibb.co/3Tpq9zX 我可以以某种方式比较输出行并继续获取行,直到顶部唯一的 5 行到达没有“不同”?在我的情况下,即使前 100 名在毫秒内返回,也没有不同

标签: postgresql performance query-optimization distinct


【解决方案1】:

SQL(尤其是对于大型表)依赖于索引来有效地运行查询。你没有告诉我们任何关于你的索引的事情,所以这个答案有一些猜测。

Creating the following index 应该对您的第一次查询有很大帮助。第一个查询没有任何问题:如果它满足您的业务需求,请继续使用它。

CREATE INDEX CONCURRENTLY tab_a_distinct 
                       ON tab_a USING BTREE
                          (col3, col4, col2, col1);

为什么会有帮助?

  1. BTREE 索引的工作方式就像按照索引中项目的顺序排序一样。
  2. 您匹配 col3col4 上的相等性,因此 postgreSQL 可以随机访问 BTREE 索引到第一个匹配行,然后按顺序扫描索引,直到找不到更多匹配行。
  3. 您希望您的输出按col2 排序,因此该列位于下一列。 postgreSQL 将扫描索引,直到它具有您需要的五行然后停止。
  4. 您需要 col2col3 的 DISTINCT 值。 postgreSQL 可以从索引中获取它们。

换句话说,这是您查询的覆盖复合索引

阅读本文以了解更多信息。 https://use-the-index-luke.com/

【讨论】:

  • 索引在那里并且查询使用索引。第一个查询解释计划(不同的)ibb.co/DKyj1xn 第一个查询解释计划(没有不同的)ibb.co/3Tpq9zX 我可以以某种方式比较输出行并继续获取行直到顶部唯一的 5 行到达没有“不同”?在我的情况下,即使前 100 名在毫秒内返回,也没有不同
猜你喜欢
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
  • 2020-04-09
  • 2018-11-17
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多