【问题标题】:Index doesn't improve performance索引不会提高性能
【发布时间】:2014-11-25 05:22:42
【问题描述】:

我的 postgres 数据库中有一个简单的表结构:

CREATE TABLE device
(
  id bigint NOT NULL,
  version bigint NOT NULL,
  device_id character varying(255),
  date_created timestamp without time zone,
  last_updated timestamp without time zone,
  CONSTRAINT device_pkey PRIMARY KEY (id )
)

我经常根据 deviceId 列查询数据。该表有 350 万行,因此会导致性能问题:

"Seq Scan on device  (cost=0.00..71792.70 rows=109 width=8) (actual time=352.725..353.445 rows=2 loops=1)"
"  Filter: ((device_id)::text = '352184052470420'::text)"
"Total runtime: 353.463 ms"

因此我在 device_id 列上创建了索引:

CREATE INDEX device_device_id_idx
  ON device
  USING btree
  (device_id );

但是我的问题是,该数据库仍然使用顺序扫描,而不是索引扫描。创建索引后的查询计划是一样的:

"Seq Scan on device  (cost=0.00..71786.33 rows=109 width=8) (actual time=347.133..347.508 rows=2 loops=1)"
"  Filter: ((device_id)::text = '352184052470420'::text)"
"Total runtime: 347.538 ms"

查询的结果是 2 行,所以我没有选择表格的大部分。我真的不明白为什么索引被忽略。我可以做些什么来提高性能?

编辑:

我的查询:

select id from device where device_id ='357560051102491A';

我在设备表上运行了analyse,但没有帮助

device_id 也包含字符。

【问题讨论】:

  • 编辑您的问题并包含查询。
  • 出于兴趣,如果deviceid 是数字,为什么varchar
  • 尝试更新表的统计信息。看起来 postgres 对此特定表的统计信息已过时。
  • 添加了查询。 DeviceId 不是数字。我在创建索引后运行了分析。

标签: sql postgresql indexing query-performance


【解决方案1】:

您可能需要查看查询。要使用索引,查询需要是可搜索的。这意味着构建查询的某些方法比其他方法更好。我不熟悉 Postgre,但在 SQl Server 中这将包括这样的东西(非常小的不良结构样本):

  • 不在连接中进行数据转换 - 而是存储数据 妥妥的
  • 不使用相关子查询 - 使用派生表或临时表 而是
  • 不使用 OR 条件 - 改用 UNION ALL

您的第一步应该是获得一本关于特定数据库性能调优的好书。它将讨论您的特定数据库引擎要避免哪些结构。

【讨论】:

  • 我已将查询添加到我的问题中。我的查询很简单,它从 350 万个表中选择了 2 行。
【解决方案2】:

将列转换为不同类型时不使用索引:

((device_id)::text = '352184052470420'::text)

相反,您可以这样做:

(device_id = ('352184052470420'::character varying))

(或者,如果您愿意,也可以将原始表中的 device_id 更改为 TEXT。)

另外,请记住在创建索引后运行analyze device,否则无论如何都不会使用它。

【讨论】:

  • 这不是问题,从查询中可以看出我没有进行任何类型转换。现在,使用相同的查询一切正常。
【解决方案3】:

似乎,时间可以解决一切。我不确定发生了什么,但目前它工作正常。 从我发布这个问题开始,我没有改变任何东西,现在我得到了这个查询计划:

"Bitmap Heap Scan on device  (cost=5.49..426.77 rows=110 width=166)"
"  Recheck Cond: ((device_id)::text = '357560051102491'::text)"
"  ->  Bitmap Index Scan on device_device_id_idx  (cost=0.00..5.46 rows=110 width=0)"
"        Index Cond: ((device_id)::text = '357560051102491'::text)"

时间细分(时区 GMT+2):

  • ~15:50 我已经创建了索引
  • ~16:00 我已经 dropepd 并重新创建了几次索引,因为它不起作用
  • 16:05 我跑了analyse device(没有帮助)
  • 16:44:49 从应用服务器 request_log 中,我可以看到执行查询的请求仍在 500 毫秒左右
  • 16:56:59 我可以看到第一个请求,需要 23 毫秒(索引开始工作!)

问题仍然存在,为什么应用索引需要大约 1:10 小时?几天前,当我在同一个数据库中创建索引时,变化是立竿见影的。

【讨论】:

  • 也许the app 正在重用准备好的查询和/或仍在事务中? -->> 如果您想知道,请查看日志。
  • 不,我正在执行查询,而且查询计划也是从 pgAdmin 手动执行的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 2015-04-28
  • 2014-01-23
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 2015-11-17
相关资源
最近更新 更多