postgresql 9.1中关于索引+排序依据+限制+三元的说明

postgresql 9.1中关于索引+排序依据+限制+三元的说明,sql,postgresql,indexing,postgresql-9.1,sqlperformance,Sql,Postgresql,Indexing,Postgresql 9.1,Sqlperformance,表: 索引: CREATE TABLE msp_adm_munic_complet_g_01 ( nom_tri character varying(64), ogc_fid serial NOT NULL ) 查询: CREATE INDEX idx_gist_msp_adm_munic_complet_g_nom_tri ON msp_adm_munic_complet_g_01 USING gist (nom_tri COLLATE pg_catalog."defau

表:

索引:

CREATE TABLE msp_adm_munic_complet_g_01
(
  nom_tri character varying(64),
  ogc_fid serial NOT NULL
)
查询:

CREATE INDEX idx_gist_msp_adm_munic_complet_g_nom_tri
  ON msp_adm_munic_complet_g_01
  USING gist
  (nom_tri COLLATE pg_catalog."default" gist_trgm_ops);
问题是:

当查询仅包含ORDER BY时,为什么它通过ORDER BY+LIMIT组合的索引而不是通过索引

当然,使用索引可以提高查询速度

我找到的唯一解释是:

但它缺乏细节

编辑1:

有限制的查询计划:

select * from msp_adm_munic_complet_g_01
ORDER BY 'potato'<->nom_tri
LIMIT 25;
无限制查询计划:

Limit  (cost=0.00..19.27 rows=25 width=590)
  ->  Index Scan using idx_gist_msp_adm_munic_complet_g_nom_tri on
msp_adm_munic_complet_g_01  (cost=0.00..2784.49 rows=3612 width=590)
      Order By: ((nom_tri)::text <-> 'potato'::text)
当然,使用索引可以提高查询速度

我认为这是问题的症结所在。当然,这是毫无疑问的

想象你有一本大书。这本书的后面有一个索引,列出了不同的术语及其出现的页码

你的老板来找你,说我想让你按字母顺序列出书中的前10个术语,并把它们的所有内容都写下来。您可以从索引开始,然后根据找到的前10个术语,转到列出的每个页面。不会花很长时间的。尤其是与阅读整本书并试图在脑海中对其进行分类,然后找出前10本书相比

接下来,你的老板来找你,说他想让你按照字母顺序列出书中的所有术语及其定义。天真地,您决定使用相同的方法。你会不断地翻阅这本书,每一页都会重温很多次。这要花很长时间

当你完成的时候,你已经阅读了整个索引,并且多次访问了书中的每一页。如果你是一个数据库,它比人类有更大的短期记忆,并且可以很容易地在它的记忆中对大的列表进行排序,那么只需从头到尾地阅读这本书,在你阅读的过程中对内容进行排序就会更快

这正是数据库中发生的情况。计算机按顺序读取磁盘文件效率更高,因为它不必来回寻找磁盘头。它一次读整页。与我们人类相比,它也有一些优势——enourmouse的短期记忆意味着它可以同时在记忆中保存数千页。但是一张大桌子和/或一个繁重的工作负载将无法解决这一问题

因此,数据库在执行每个查询之前都会对其进行分析。它将尝试估计返回的表的比例,以及它对随机访问页面和顺序访问页面的成本的了解,以及关于表中值分布的其他表统计信息。在某个时刻,它会说扫描整个表并忘记索引会更有效

您可能会认为这种过于简单的类比不适用于三叉图索引,但它确实适用。索引不是按字母顺序排列的,但构建排序列表的机制是相同的,只是并非所有索引类型都适合在任何情况下返回排序的行。许多索引类型允许您快速查找某些内容,但不能保持键的顺序。在内置索引类型中,只有b-树适合返回已排序的数据。实际上,我有点惊讶于trigram索引可以用于此。但这取决于顺序表达式——我想这个索引确实会按顺序返回数据

如果按排序顺序遍历行是此表上的常见操作,则可以采取一些措施使其运行更快

如果您使用的是Postgresql 9.2,您可能可以使用扫描。在您的查询中,您选择的是所有列,这意味着它不能使用仅索引扫描,而且在任何情况下,我认为您都不能将仅索引扫描与三元索引一起使用

您可以使用该命令将表按与索引相同的顺序排列,尽管在插入或更新数据时它不会保持这种方式,因此需要在经常更新的表中定期执行

您可能会发现,该表将受益于对其上保存的数据进行微调。更多的统计数据可能会使它更频繁地使用索引

您可以调整规划器用于估算顺序读取数据与随机访问数据的相对成本的参数。你可以用固态磁盘代替老式的旋转磁盘


当然,更多的RAM不会损害数据库。

请向我们展示执行计划,解释分析您的查询,并解释为什么您认为它应该使用索引。你认为遗嘱执行人应该采取什么具体步骤?试着给他们估算一些成本——如果你不知道某些步骤的相对成本,不要担心,只要猜测就行了。仔细考虑这一点是有用的,即使数字与实际情况不符。当我阅读您引用的PG文档中的解释时,关于为什么在这种情况下可能不使用索引的解释对我来说是有意义的。你可能需要解释你为什么这么想 这一解释缺乏细节。
Sort  (cost=1847.59..1856.62 rows=3612 width=590)
  Sort Key: (('potato'::text <-> (nom_tri)::text))
  ->  Seq Scan on msp_adm_munic_complet_g_01  (cost=0.00..682.15 rows=3612 width=590)