【问题标题】:Why is my SQL query not using the index?为什么我的 SQL 查询不使用索引?
【发布时间】:2012-08-15 19:39:16
【问题描述】:

这是我的查询:

explain analyze SELECT levenshtein('google', lower(s."Name"), 2, 2, 1), d."Domain"
FROM   analyst_sld s, analyst_domain d
WHERE  levenshtein('google', lower(s."Name"), 2, 2, 1) < 4 AND s.id = d."SLDk_id"
ORDER  BY 1;

这是输出:

                                                                  QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=5340874.17..5383497.72 rows=17049420 width=46) (actual time=136245.943..138709.585 rows=1022346 loops=1)
   Sort Key: (levenshtein('google'::text, lower((s."Name")::text), 2, 2, 1))
   Sort Method:  external sort  Disk: 78656kB
   ->  Hash Join  (cost=122111.24..1195078.39 rows=17049420 width=46) (actual time=16730.865..133020.419 rows=1022346 loops=1)
         Hash Cond: (d."SLDk_id" = s.id)
         ->  Seq Scan on analyst_domain d  (cost=0.00..417631.20 rows=17049420 width=38) (actual time=0.036..64677.170 rows=17041042 loops=1)
         ->  Hash  (cost=103151.93..103151.93 rows=1090665 width=16) (actual time=16730.443..16730.443 rows=1071 loops=1)
               ->  Seq Scan on analyst_sld s  (cost=0.00..103151.93 rows=1090665 width=16) (actual time=14.742..16726.358 rows=1071 loops=1)
                     Filter: (levenshtein('google'::text, lower(("Name")::text), 2, 2, 1) < 4)
 Total runtime: 139557.853 ms

为什么不使用索引,而是顺序扫描? 另外,“Hash Join”和“Hash Cond”是什么意思?

EDIT_1: 索引:

                                      Table "public.analyst_domain"
     Column     |           Type           |                          Modifiers
----------------+--------------------------+-------------------------------------------------------------
 ID             | integer                  | not null default nextval('analyst_domain_id_seq'::regclass)
 Domain         | character varying(255)   | not null
 SLDk_id        | integer                  |
Indexes:
    "analyst_domain_pkey" PRIMARY KEY, btree ("ID")
    "analyst_domain_Domain_key" UNIQUE, btree ("Domain")
    "analyst_domain_sldk" btree ("SLDk_id")



                                      Table "public.analyst_sld"
     Column     |           Type           |                        Modifiers
----------------+--------------------------+----------------------------------------------------------
 id             | integer                  | not null default nextval('analyst_sld_id_seq'::regclass)
 Name           | character varying(255)   | not null
Indexes:
    "analyst_sld_pkey" PRIMARY KEY, btree (id)
    "analyst_sld_Name_key" UNIQUE, btree ("Name") CLUSTER
    "analyst_sld_upper_idx" btree (upper("Name"::text))

【问题讨论】:

  • 你的索引是什么样的?
  • 可以在帖子中添加表定义吗?我们也需要索引定义。

标签: sql postgresql indexing plpgsql


【解决方案1】:

它对analyst_sld 使用顺序扫描,因为这是进行levenshtein 过滤的唯一方法。如果你认为这是一个重要的过滤器,你可以

CREATE INDEX lev_index on 
 analyst_sld (levenshtein('google', lower("Name"), 2, 2, 1));

就哈希而言:Postgres 已决定加入表的最佳方法是在连接列上查找相等的哈希(并在桶有多个条目的情况下解决它们)。您的表有多少元素,您希望连接有多大?

【讨论】:

    【解决方案2】:

    关于 DDL:在 pgAdmin III 中 - 当您在树中选择一个对象(表/索引/等)时,DDL 将显示在右侧的窗口中。

    DDL 将提供比以下基于假设的猜测更好的答案。

    至于原因,根据给出的信息并假设连接条件上的主键索引,这是我的猜测:d 比 s 大约 17 倍,s 正在被一个未索引的函数过滤,所以优化器不知道该过滤器的选择性。使用 s.name 的行查找的索引扫描或顺序扫描哪个更快?根据优化器顺序获胜。

    【讨论】:

    • d 比 s 大约 17 倍。
    • @alfonzo1955:在不知道 SLDk_id 的分布情况下(例如,有多少是 NULL,或者还有其他主要值),让我们假设它是一个很好的均匀分布;换句话说:s 中的每一行在 d 中都有一行。由于优化器不知道 levenshtein 函数要消除多少行,它可能导致最坏的情况:所有行都连接。读取每一行的索引条目,然后从实际表中读取每一行的名称,比简单地扫描整个表要慢,尤其是当 d 非常窄时(
    • 抱歉,它应该是“...尤其是当 s 太窄的时候...”在 5 分钟的编辑窗口后捕获。
    • 那么有没有办法强制它使用索引呢?
    • 您可以考虑以下几点: 1) 是否分析了表和索引? IE。我们是否向优化器提供了我们可以提供的所有信息?
    【解决方案3】:

    虽然我目前还不是 PostgreSQL 专家,但由于使用了 levenshtein 函数,它看起来正在使用顺序扫描。我不知道这个函数的细节,但通常可以基于函数评估创建一个索引;但是我冒险猜测“Google”字符串在你的情况下是可变的,所以我不知道索引会有多大用处......

    【讨论】:

    • 它正在执行顺序匹配 s.id 和 d."SLDk_id" 这不应该发生。
    • 哦,确实!我首先看的是内部循环。没有表结构和索引列表,任何人都无能为力...
    猜你喜欢
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    相关资源
    最近更新 更多