索引并没有提高性能

时间:2014-09-30 14:24:44

标签: sql postgresql indexing query-performance

我的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列查询数据。该表有3,5万行,因此会导致性能问题:

"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也包含字符。

3 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

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

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

相反,你可以这样做:

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

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

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

答案 2 :(得分:0)

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

"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来自app server request_log,我可以看到执行查询的请求仍然需要 500 ms
  • 16:56:59我可以看到第一个请求, 23 ms (索引开始工作!)

问题仍然存在,为什么需要大约1:10小时才能应用索引?几天前,当我在同一个数据库中创建索引时,立即进行了更改。