【问题标题】:Index not being used when joining tables连接表时未使用索引
【发布时间】:2017-11-25 17:23:08
【问题描述】:

我们有四个表:

  • 列表
  • influencer_lists(加入表)

这是查询:

SELECT influencer_lists.influencer_id 
FROM influencer_lists
LEFT OUTER JOIN lists ON lists.id = influencer_lists.list_id
WHERE influencer_lists.influencer_id IN (12, 95, 33, 23, 35, 36, 27, 41, 42, 43, 45, 30) 
AND "lists"."user_id" = 1

在做解释的时候,要注意两点:

  1. 在查找影响者 ID 时,有时未使用索引
  2. 索引被用于

解释输出:

Nested Loop  (cost=0.28..73.59 rows=9 width=4) (actual time=0.031..0.187 rows=4 loops=1)
->  Seq Scan on influencer_lists  (cost=0.00..10.82 rows=9 width=8) (actual time=0.016..0.152 rows=5 loops=1)
Filter: (influencer_id = ANY ('{12,95,33,23,35,36,27,41,42,43,45,30}'::integer[]))
Rows Removed by Filter: 308
->  Index Scan using lists_pkey on lists  (cost=0.28..6.96 rows=1 width=4) (actual time=0.005..0.005 rows=1 loops=5)
Index Cond: (id = influencer_lists.list_id)
Filter: (user_id = 1)
Rows Removed by Filter: 0
Planning time: 0.621 ms
Execution time: 0.235 ms

我们希望改进查询时间。我们该怎么做?

谢谢。

【问题讨论】:

  • “我们有四个表”。我数了两个。
  • 您对user_id 的值有一个选择子句,它否定了outer join 的效果。也许您需要将该子句从 where 移动到 on 标准。
  • 使用 seq 扫描检索 300 行的成本很可能比通过索引查找要小得多。如果那是一个窄表,那么这 300 行很可能只存储在硬盘上的 3 或 4 个块中

标签: sql postgresql


【解决方案1】:

我建议的第一件事是更新所涉及表的统计信息。如果您是体验性能,这是一个很好的开始。

 ANALYZE [tablename] ;

其次,因为此列上有索引,并不意味着它会一直被使用。 'IN' 子句中的值范围可能包含太多 id,无法保证使用索引。您可以尝试个人 id = [value]

【讨论】:

    【解决方案2】:

    如果 SELECT 返回表中所有行的大约 5-10%(取决于配置设置和数据的存储。这不是一个硬数字),则顺序扫描比索引快得多扫描。

    索引扫描需要对每一行进行多次 IO 操作(在索引中查找该行,然后从堆中检索该行)。顺序扫描每行只需要一个 IO - 甚至更少,因为磁盘上的一个块(页)包含不止一行,因此可以通过单个 IO 操作获取多行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2013-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多