SQL性能和替代解决方案

时间:2019-07-14 22:07:28

标签: sql postgresql

我在postgresql数据库中关注了2个表-

table1

  • col1_id(整数)
  • col2(文本)
  • col3(文本)
  • col4(文本)
  • col5(数字(1,0))
  • col6(数字(9,0))
  • col7_created_date(时间戳),
  • col8(文本)
CREATE UNIQUE INDEX col1_pkey ON table1 USING btree (col1_id),  

table2

  • col1_id(整数)
  • tab2_col2(文本)
  • tab3_col3(文本)
  • tab4_col4(整数)
  • tab5_col5(文本)
CREATE UNIQUE INDEX table2_pkey ON table2 USING btree (col1_id, tab3_col3)

FOREIGN KEY (col1_id) REFERENCES table1(col1_id) ON UPDATE RESTRICT ON DELETE RESTRICT

注意:从上面的表定义中,您将了解到table1中的col1_id不仅是table2中的外键,而且是主键的一部分,以及table2中的tab3_col3以支持1:Many关系。

这里的问题是table1有10,000,000行&table2有50,00,000条记录。因此,我的查询执行至少需要5秒,这是我的查询-

查询1:

SELECT * 
FROM table1 t1  
WHERE (col6 >= ?)  
  AND col5 IN (?)  
  AND (t1.col8 LIKE ? OR t1.col8 LIKE ?) 
ORDER BY col7_created_date DESC 
LIMIT 50

Query2:

SELECT COUNT(*) 
FROM table1 t1 
LEFT JOIN table2 t2 ON t2.col1_id = t1.col1_id 
WHERE t1.col7_created_date > ? 
  AND t2.tab4_col4 = ? 
  AND t2.tab3_col3 IN (?, ?) 
  AND a.tab2_col2 IN (?) 

要了解的要点:

  1. table2应该具有单独的id列作为主键以具有良好的性能,因为复合键会降低表中大量数据的速度,从而降低性能。我可以解决这个问题。
  2. 我还可以删除table1和table2中的一些旧记录,但是到目前为止,这对我来说不是一个选择。
  3. 在Query1中,我无法删除“ col7_created_date DESC”,因为我只想要前50条记录,而分页由业务逻辑控制。
  4. Query1中的“ LIKE”搜索是动态创建的,可以是1或2。

问题:

  1. 如果我在t1.col8(Query1)上创建索引,它将提高性能吗?如果是这样,是否有创建索引的有效方法? (注意:t1.col8是逗号分隔的文本,最多4个)
  2. 我应该做些什么来提高Query1和Query2的性能,我愿意更改DDL。有任何建议吗?

3 个答案:

答案 0 :(得分:0)

您的表有100万和500万记录,对吗?索引访问确实没什么大不了的。

索引在query1中对您没有任何帮助。考虑一下,为了选择一条记录,优化器必须访问col5和col6和col8-无法避免访问表,因为索引只是没有它们。不知道在哪里可以得到有关复合索引的信息-您可以创建查询指定的索引,如果查询需要col5和col6以及col8和col1和col2,这就是您要做的。因为您拥有的索引比完全扫描表要好得多,这就是您现在正在做的。考虑哪一列可提供最佳选择性,并将其放在综合索引中的首位。

您的Query2是否也给您带来麻烦?它的执行计划是什么?

答案 1 :(得分:0)

在整数字段上创建索引可提供更快的查找,但是在您的情况下,b树索引应该起作用。同样,具有高度唯一性(几乎没有重复值)的列也非常适合用于索引。因此,如果t1.col8具有此属性,则应很好地对其进行索引。有关更多参考,请参见this

答案 2 :(得分:0)

运行说明分析以检查查询的执行时间。explain

查询1:

SELECT * 
FROM table1 t1  
WHERE (col6 >= ?)  
  AND col5 IN (?)  
  AND (t1.col8 LIKE ? OR t1.col8 LIKE ?) 
ORDER BY col7_created_date DESC 
LIMIT 50

您可以在col6和col5上添加复合索引。这些都是数字列,因此会增加执行时间。此外,您还使用IN查询,这会使数据库变慢。.避免使用in查询

与第二个查询相同。

创建不同的索引后,您可以运行此代码。

explain analyze SELECT * 
FROM table1 t1  
WHERE (col6 >= ?)  
  AND col5 IN (?)  
  AND (t1.col8 LIKE ? OR t1.col8 LIKE ?) 
ORDER BY col7_created_date DESC 
LIMIT 50

哪位会给您带来时间的想法。

您也可以将其粘贴,以便我可以建议更多索引。