为什么 PostgreSQL (9.1) 不使用索引进行简单的相等选择?

2023-12-22

我的桌子lead有一个索引:

\d lead
...
Indexes:
    "lead_pkey" PRIMARY KEY, btree (id)
    "lead_account__c" btree (account__c)
    ...
    "lead_email" btree (email)
    "lead_id_prefix" btree (id text_pattern_ops)

为什么 PG (9.1) 不使用索引来进行这种简单的相等选择?电子邮件几乎都是独一无二的......

db=> explain select * from lead where email = 'blah';
                         QUERY PLAN
------------------------------------------------------------
 Seq Scan on lead  (cost=0.00..319599.38 rows=1 width=5108)
   Filter: (email = 'blah'::text)
(2 rows)

其他索引命中查询似乎没问题(尽管我不知道为什么这个查询不只使用 pkey 索引):

db=> explain select * from lead where id = '';
                                  QUERY PLAN
------------------------------------------------------------------------------
 Index Scan using lead_id_prefix on lead  (cost=0.00..8.57 rows=1 width=5108)
   Index Cond: (id = ''::text)
(2 rows)

db=> explain select * from lead where account__c = '';
                                    QUERY PLAN
----------------------------------------------------------------------------------
 Index Scan using lead_account__c on lead  (cost=0.00..201.05 rows=49 width=5108)
   Index Cond: (account__c = ''::text)
(2 rows)

起初我认为这可能是由于没有足够明确的价值观email。例如,如果统计数据表明email is blah对于表的大部分内容,顺序扫描速度更快。但事实并非如此:

db=> select count(*), count(distinct email) from lead;
 count  | count
--------+--------
 749148 | 733416
(1 row)

即使我强制关闭 seq 扫描,规划器也会表现得好像没有其他选择:

db=> set enable_seqscan = off;
SET
db=> show enable_seqscan;
 enable_seqscan
----------------
 off
(1 row)

db=> explain select * from lead where email = '[email protected] /cdn-cgi/l/email-protection';
                            QUERY PLAN
---------------------------------------------------------------------------
 Seq Scan on lead  (cost=10000000000.00..10000319599.38 rows=1 width=5108)
   Filter: (email = '[email protected] /cdn-cgi/l/email-protection'::text)
(2 rows)

也尝试过EXPLAIN ANALYZE:

db=> explain analyze select * from lead where email = '[email protected] /cdn-cgi/l/email-protection';
                                                         QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
 Seq Scan on lead  (cost=10000000000.00..10000319732.76 rows=1 width=5102) (actual time=77845.244..77845.244 rows=0 loops=1)
   Filter: (email = '[email protected] /cdn-cgi/l/email-protection'::text)
 Total runtime: 77857.215 ms
(3 rows)

这里是\d输出(抱歉,必须模糊列名,并进行裁剪以适应 SO 的限制;请参阅未裁剪的版本http://pastebin.com/ve3gzJpY http://pastebin.com/ve3gzJpY):

                                 Table "lead"
                   Column                   |            Type             | Modifiers 
--------------------------------------------+-----------------------------+-----------
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | real                        | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | boolean                     | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 ...
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 email                                      | text                        | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | boolean                     | 
 ...
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 account__c                                 | text                        | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 ...
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | text                        | 
 id                                         | text                        | not null
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | real                        | 
 ...
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | timestamp without time zone | 
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | real                        | 
Indexes:
    "lead_pkey" PRIMARY KEY, btree (id)
    "lead_account__c" btree (account__c)
    "lead_XXXXXXXXXXXXXXXXXXXXXX" btree (XXXXXXXXXXXXXXXXXXXXXX)
    "lead_XXXXXXXXXXXXXXXXXXXXXX" btree (XXXXXXXXXXXXXXXXXXXXXX)
    "lead_XXXXXXXXXXXXXXXXXXXXXX" btree (XXXXXXXXXXXXXXXXXXXXXX)
    "lead_email" btree (email)
    "lead_id_prefix" btree (id text_pattern_ops)

Here is pg_dump --schema-only -t lead(再次看到未裁剪的http://pastebin.com/ve3gzJpY http://pastebin.com/ve3gzJpY,也具有唯一的列名称,以防有助于再现性):

--
-- PostgreSQL database dump
--

SET statement_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;

SET default_tablespace = '';

SET default_with_oids = false;

--
-- Name: lead; Type: TABLE; Schema: public; Owner: pod; Tablespace: 
--

CREATE TABLE lead (
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX real,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX text,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX boolean,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX text,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX text,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX date,
    ...
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX text,
    account__c text,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX text,
    ...
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX text,
    id text NOT NULL,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX real,
    ...
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX timestamp without time zone,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX real
);


ALTER TABLE lead OWNER TO pod;

--
-- Name: lead_pkey; Type: CONSTRAINT; Schema: public; Owner: pod; Tablespace: 
--

ALTER TABLE ONLY lead
    ADD CONSTRAINT lead_pkey PRIMARY KEY (id);


--
-- Name: lead_account__c; Type: INDEX; Schema: public; Owner: pod; Tablespace: 
--

CREATE INDEX lead_account__c ON lead USING btree (account__c);


--
-- Name: lead_XXXXXXXXXXXXXXXXXXXX; Type: INDEX; Schema: public; Owner: pod; Tablespace: 
--

CREATE INDEX lead_XXXXXXXXXXXXXXXXXXXX ON lead USING btree (XXXXXXXXXXXXXXXXXXXX);


--
-- Name: lead_XXXXXXXXXXXXXXXXXXXX; Type: INDEX; Schema: public; Owner: pod; Tablespace: 
--

CREATE INDEX lead_XXXXXXXXXXXXXXXXXXXX ON lead USING btree (XXXXXXXXXXXXXXXXXXXX);


--
-- Name: lead_XXXXXXXXXXXXXXXXXXXX; Type: INDEX; Schema: public; Owner: pod; Tablespace: 
--

CREATE INDEX lead_XXXXXXXXXXXXXXXXXXXX ON lead USING btree (XXXXXXXXXXXXXXXXXXXX);


--
-- Name: lead_email; Type: INDEX; Schema: public; Owner: pod; Tablespace: 
--

CREATE INDEX lead_email ON lead USING btree (email);


--
-- Name: lead_id_prefix; Type: INDEX; Schema: public; Owner: pod; Tablespace: 
--

CREATE INDEX lead_id_prefix ON lead USING btree (id text_pattern_ops);


--
-- PostgreSQL database dump complete
--

一些PG目录咒语:

db=> select * from pg_index where indexrelid = 'lead_email'::regclass;
 indexrelid | indrelid  | indnatts | indisunique | indisprimary | indisexclusion | indimmediate | indisclustered | indisvalid | indcheckxmin | indisready | indkey | indcollation | indclass | indoption | indexprs | indpred
------------+-----------+----------+-------------+--------------+----------------+--------------+----------------+------------+--------------+------------+--------+--------------+----------+-----------+----------+---------
  215251995 | 101034456 |        1 | f           | f            | f              | t            | f              | t          | t            | t          | 101    | 100          | 10043    | 0         | ¤        | ¤
(1 row)

一些区域设置信息:

db=> show lc_collate;
 lc_collate  
-------------
 en_US.UTF-8
(1 row)

db=> show lc_ctype;
  lc_ctype   
-------------
 en_US.UTF-8
(1 row)

我搜索了很多过去的 SO 问题,但没有一个是关于像这样的简单相等查询的。


要解决这些问题,您必须在故障排除步骤之间对表运行 VACUUM ANALYZE,以查看哪些方法有效。否则你可能不知道究竟发生了什么变化。因此,请先尝试并再次运行,看看是否可以解决问题。

接下来要运行的步骤(在每个步骤之间运行真空分析和测试用例)是:

ALTER TABLE lead ALTER COLUMN email SET STATISTICS 1000;

也许这会解决它。也许不会。

如果这不能解决问题,请仔细查看 pg_stat 视图:

SELECT * FROM pg_stat WHERE table_name = 'lead';

请仔细阅读以下内容,看看 pg_stat 中有哪些错误;

http://www.postgresql.org/docs/9.0/static/planner-stats.html http://www.postgresql.org/docs/9.0/static/planner-stats.html

编辑:非常清楚,vacuum analyse并不是故障排除的全部。但是,它必须在故障排除步骤之间运行,否则您无法确定规划器是否考虑了正确的数据。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 PostgreSQL (9.1) 不使用索引进行简单的相等选择? 的相关文章

随机推荐

  • 二值图像的简单多斑点检测?

    如果存在给定的图像二维数组 其中阈值已经完成并且现在是二进制信息 有没有什么特殊的方法来处理这个图像 以便我在图像上获得多个斑点的坐标 我无法使用 openCV 因为这个过程需要在 C 语言的自定义模拟器上同时运行 10 多个模拟机器人 我
  • 使用 local-name() 获取 XSLT 中的第一个子节点

    假设我们有这个简单的 xml
  • SQL Server 中的自定义聚合函数(concat)

    问题 我想编写一个自定义聚合函数 用于连接分组依据上的字符串 这样我就可以做一个 SELECT SUM FIELD1 as f1 MYCONCAT FIELD2 as f2 FROM TABLE XY GROUP BY FIELD1 FIE
  • 使用 Subclipse 1.6.5 时出现未知图标

    我在 Eclipse IDE 中使用 SVN 插件 Subclipse 我最近注意到我的一个目录被标记为下面所示的图标 在查看了 Subclipse 标签装饰器后 我没有看到这个 有谁知道它代表什么吗 这意味着您有版本化的 SVN 属性修改
  • 如何在数据库中存储具有动态数量属性的数据

    我有许多不同的对象 它们具有不同数量的属性 到目前为止 我已将数据保存在 XML 文件中 这可以轻松地允许不断变化的属性数量 但我正在尝试将其移至数据库 您存储这些数据的首选方式是什么 到目前为止我已经确定的一些策略 在对象的表中有一个名为
  • 为什么 (a | b ) 等于 a - (a & b) + b?

    我正在寻找一种使用 Oracle 数据库执行 BITOR 的方法 并遇到了一个仅使用 BITAND 的建议 将 BITOR a b 替换为 a b BITAND a b 我手动测试了几次 并验证它似乎适用于我能想到的所有二进制数 但我无法快
  • 将图像显示到 Windows 窗体中

    我想在 Windows 窗体上显示图像 但我已经这样做了 但图像没有显示出来 我哪里做错了 这是代码 private void Images object sender EventArgs e PictureBox pb1 new Pict
  • 如何使用 php 验证不一致端点?

    我在创建 Discord 机器人时遇到一些问题 我希望它能够响应斜杠命令 但要做到这一点 我需要验证端点 我使用的是 PHP 7 4 并且无法使用任何外部库 托管在不允许使用它们的服务器上 我找到了 PHP 的文档 但它们确实需要库才能工作
  • 在 Xcode 上的图像上添加文本

    我想制作一个类似于某些贺卡应用程序的 iPhone 应用程序 我可以在一些预先准备好的背景图像 卡片 上写入文本 我该如何写这段文字 如何将背景图像 文本保存在一个图像文件中 Thanks 这是一种将字符串刻录成图像的方法 您可以调整字体大
  • 最快的实时解压算法

    我正在寻找一种算法 以最小的开销实时解压缩数据块 1k 30k 压缩速度最好要快 但不如解压速度那么重要 据我所知 LZO1X 是最快的 我错过了什么吗 理想情况下 该算法不受 GPL 约束 lz4 https github com lz4
  • 如何清除 MassTransit 队列?

    我想在集成测试设置例程中删除队列中的所有消息 如何实现 谷歌搜索 智能感知暴力没有运气 如果重要的话 我使用 RabbitMq 作为传输 无法从 MassTransit 内的队列中 删除 对于测试 您可以通过使用临时的随机队列 URIrab
  • 如何使用 Polymer 将自定义字体导入应用程序或元素?

    如何将自定义字体导入 Polymer 应用程序或元素 根据 tweightman 的聚合物松弛通道 https polymer slack com
  • React Hook useEffect 缺少依赖项:“list”

    运行以下代码后 我收到以下错误 React Hook useEffect 缺少依赖项 list 包含它或删除依赖项数组react hooks exhaustive deps 我找不到警告的原因 import React useState u
  • 在控制器构造函数中使用 User.Identity.Name 定义用户

    对于要与用户帐户交互的操作 除了在调用控制器上的任何操作后立即将该对象添加到 ViewData TheUser 之外 我还想创建一个 TheUser 对象 如果用户已登录 它将从数据库中获取用户的信息 如果没有 TheUser 对象将为空
  • 是否可以编写命令来支持多行参数,即其中包含换行符,如heredocs?

    Overview 如何编写一个 sbt 命令来支持其中包含换行符的参数 heredocs http en wikipedia org wiki Here document 我想要一个 sbt 命令 用户可以在其中粘贴多行文本块 然后将其处理
  • 自定义进度条中的圆角渐变

    你会如何制作圆角渐变ProgressBar就像屏幕上一样 我现在拥有的 pb shape xml
  • 在服务器上使用旧版本的 SVN 进行签出

    我已经厌倦了检查这个存储库 但由于主机和客户端计算机上的 SVN 版本不同 它返回一个解压错误 svn co http svn rdlab cs upc edu subversion asiya public asiya A asiya b
  • 使用现有项目将 json 反序列化为 C# 列表

    给定以下课程 class Report public Report this Fields new List
  • Sqoop 将所有表导入 hive 时遇到以下语句

    默认情况下 表将移动到 HDFS 而不是仓库目录 user hive warehouse sqoop import all tables num mappers 1 connect jdbc mysql quickstart clouder
  • 为什么 PostgreSQL (9.1) 不使用索引进行简单的相等选择?

    我的桌子lead有一个索引 d lead Indexes lead pkey PRIMARY KEY btree id lead account c btree account c lead email btree email lead i