使用order by时,在大型表上查询速度慢

时间:2015-10-22 10:37:33

标签: sql postgresql indexing postgresql-9.3 postgresql-performance

我有一个包含~30M元组的表。该表看起来像:

id | first_name | last_name | email
-----------------------------------------
1  | foo        | bar       | foo@bar.com

还有first_name的索引(btree索引)和last_name的其他索引。

以下查询大约需要200毫秒才能返回结果:

SELECT  
  * 
FROM my_table 
 WHERE (first_name ILIKE 'a%') 
 LIMIT 10 OFFSET 0

但是下一个花了大约15秒(添加订单)

SELECT  
  * 
FROM my_table 
 WHERE (first_name ILIKE 'a%') 
 ORDER BY last_name asc, first_name asc 
 LIMIT 10 OFFSET 0 

我可以做些什么来改善上一次查询的效果?

3 个答案:

答案 0 :(得分:2)

此查询有两种索引选择:

SELECT t.* 
FROM my_table 
WHERE first_name ILIKE 'a%'
ORDER BY last_name asc, first_name asc 
LIMIT 10 OFFSET 0 ;

一个用于WHERE子句。最好的索引是my_table(first_name)。第二种可能性是使用ORDER BYmy_table(last_name, first_name)

的索引

哪个更好取决于您拥有的数据。如果总体性能是目标,您可能想要尝试两者看哪些更好用。

最后,计算出的索引可能是最好的方法。对于您的情况,请将查询写为:

SELECT t.* 
FROM my_table 
WHERE lower(substr(first_name, 1, 1)) = 'a'
ORDER BY last_name asc, first_name asc 
LIMIT 10 OFFSET 0 ;

然后,您想要的索引是mytable(lower(substr(first_name, 1, 1)), last_name, first_name)。此索引可用于WHEREORDER BY,这对于此查询应该是最佳的。

答案 1 :(得分:1)

我假设以下索引会加快ORDER BY

create index my_table_lname_fname on my_table (last_name, first_name)

答案 2 :(得分:0)

CREATE INDEX my_table_idx1 ON my_table (last_name ASC NULLS LAST, first_name ASC NULLS LAST);

一些注释没有特别的顺序:

  • ASC NULLS LAST是默认设置,但我想如果您想要订购,我会说明一下。
    • 这是多列索引可以帮助您的极少数情况之一。 通常建议您创建大量单列索引,并允许查询优化器选择要使用的索引,而不是强制执行决策。
    • 我注意到那里的ILIKE不具备性能,可能是你真正的问题除非你正在使用pg_trgm包以及GIST索引。