深入学习SQL及调优

关于SQL调优的几种方式,当然要看情况使用。结合自己的表结构和自己使用到的查询条件,使用最佳的优化方式。

局部索引(partial indexs)

假设我们经常使用特性过滤查询,而这种特性只存在个别行之中,我们就可以是使用partial indexs。 例如以下查询:

    EXPLAIN ANALYZE SELECT id from tags WHERE name LIKE 'snow%' ORDER BY media_count DESC LIMIT 10;      
    QUERY PLAN   
    ---------                                                                  
     Limit  (cost=1780.73..1780.75 rows=10 width=32) (actual time=215.211..215.228 rows=10 loops=1)
       ->  Sort  (cost=1780.73..1819.36 rows=15455 width=32) (actual time=215.209..215.215 rows=10 loops=1)
             Sort Key: media_count
             Sort Method:  top-N heapsort  Memory: 25kB
             ->  Index Scan using tags_search on tags_tag  (cost=0.00..1446.75 rows=15455 width=32) (actual time=0.020..162.708 rows=64572 loops=1)
                   Index Cond: (((name)::text ~>=~ 'snow'::text) AND ((name)::text ~<~ 'snox'::text))
                   Filter: ((name)::text ~~ 'snow%'::text)
     Total runtime: 215.275 ms
    (8 rows)

注意Postgres必须对15,000行进行排序才能得到正确的结果。因为标签(例如)显示长尾模式,所以我们可以先尝试对超过100张照片的标签进行查询; 对超过100张照片的标签创建索引

CREATE INDEX CONCURRENTLY on tags (name text_pattern_ops) 
WHERE media_count >= 100

建完索引之后再来看看执行计划,如下:

EXPLAIN ANALYZE SELECT * from tags WHERE name LIKE 'snow%' AND media_count >= 100 ORDER BY media_count DESC LIMIT 10;
QUERY PLAN
 Limit  (cost=224.73..224.75 rows=10 width=32) (actual time=3.088..3.105 rows=10 loops=1)
   ->  Sort  (cost=224.73..225.15 rows=169 width=32) (actual time=3.086..3.090 rows=10 loops=1)
         Sort Key: media_count
         Sort Method:  top-N heapsort  Memory: 25kB
         ->  Index Scan using tags_tag_name_idx on tags_tag  (cost=0.00..221.07 rows=169 width=32) (actual time=0.021..2.360 rows=924 loops=1)
               Index Cond: (((name)::text ~>=~ 'snow'::text) AND ((name)::text ~<~ 'snox'::text))
               Filter: ((name)::text ~~ 'snow%'::text)
 Total runtime: 3.137 ms
(8 rows)

Postgres只需要访问169行,这要快得多。Postgres的查询规划器也非常擅长评估约束;如果您后来决定查询包含超过500张照片的标签,因为这些是这个索引的子集,所以它仍然使用正确的部分索引。

功能性索引 (Functional indexs)

在我们的一些表上,索引是非常长的字符串(例如,64个字符base64令牌),在这些字符串上创建索引最终会复制大量数据。对于这些,Postgres的功能索引功能非常有用

CREATE INDEX CONCURRENTLY on tokens (substr(token), 0, 8)

虽然会有多行匹配这个前缀,但是让Postgres匹配这些前缀然后过滤掉是非常快的,并且得到的索引的大小是为整个字符串建立索引的十分之一。

表重组使其数据紧凑 (pg_reorg For Compaction)

随着时间的推移,Postgres表可能在磁盘上被分割(例如,由于Postgres的MVCC并发模型)。而且,在大多数情况下,行插入顺序与希望返回行的顺序不匹配。例如,如果您经常查询由一个用户创建的所有like,那么将这些like放在磁盘上是有帮助的,这样可以最小化磁盘查找。 通过以下五个步骤,重组表。

    1. 获取表的独占锁
    2. 创建一个临时表来积累更改,并在原始表上添加一个触发器,该触发器将复制对这个临时表的任何更改
    3. 使用SELECT FROM…ORDER BY创建表,它将在磁盘上按索引顺序创建一个新表
    4. 同步SELECT from启动后临时表中的更改
    5. 转换到新表。

自动模式和异步模式(Autocommit mode and async mode in psycopg2)

通过python pg的异步库可以实现异步访问postgress数据库.
1.Python 的 PostgreSQL 异步驱动 aiopg
2.asyncpg —— PostgresSQL 的开源Python 异步客户端开发包

相关链接

1. postgreSQl 批量执行sql的方式
2. Full Stack Python 系列之 5.5 PostgreSQL

Life is more than the present.