PostgreSQL 的查询优化系列的文字已经到了第七期,这期的主题其实主要是要分析我们要优化什么样的SQL ,在优化的前,我们需要去区分什么是短查询,什么是长连接查询。
首先为什么要区分短查询和长连接查询,主要还是优化的方法是不一样的,接下来的问题是,我们怎么能区分短查询,一般来说短查询有以下几个特点
1 查询的表比较小,从几行到几万行。
2 查询的结果数量小,查询带有条件
3 在查询中,不会通过大量的计算,如聚合,最终得出结果
4 查询中的开销很小
这样的查询我们可以理解为短查询,当然上面的条件是或的条件方式,并不是AND 的方式,但即使如此界定一个短查询仍然是一件比较凭经验的事情。
短查询的优化可以关注一下几点
1 展示字段的选择
这点在查询中十分重要,很多情况下,多添加一个字段尤其的字符型的字段,会给你查询数据中的传输数据以及POSTGRESQL 客户进程添加更多的负担,所以在优化一个查询的情况第一个问题就是要看看你展示的字段是否能减少,并且这个事情是优化一个短SQL中最简单和最有效的第一步。
2 查询中的索引的选择
一般来说索引的选择主要涉及几个方面,
1 表的数据量的大小, 表的数据量太小即使建立了索引的情况下,也不会使用索引
2 查询字段,建立字段的数据分布的情况,数据分布情况月多种多样,这样的情况下索引的查询效率会高,如果数据的分布情况比较单一,则索引建立并不会提高查询的速度,很多情况下,对于业务的熟悉会有利于你对查询中的索引建立的效能的确定。
3 唯一索引和主键的区别,这个问题其实在建立唯一索引的时候会被提出,尤其是之间的区别,根据数据库的情况来看这里两者的区别,可以理解为主键是不允许为空存在的整体列值都不相同的值的序列,而唯一索引是允许存在NULL的。这点是两者的区别。
同时基于一些其他数据库的主键的建立方式,可能对主键的认知会产生偏差,就是基于POSTGRESQL 的主键并不存在必须使用递增方式的逻辑组成方式,
并且基于主键的思路,主键是对任何存在数据表中的记录,进行标定的义务,而唯一索引则是为数据查找所存在的,并不需要对每一条记录负责,尤其是NULL 的列记录。
在查询操作中,如果使用的唯一索引在Join 操作中会产生类似下方的信息
4 索引中存在的变化和失效的问题
建立索引是处理数据库优化的或者建立应用中,程序员第一个考虑的数据库方式优化查询的方案之一,一般来说我们比较怕在查询的过程中提及在条件的左端出现对于条件的变化。这样的操作会导致一些我们使用索引的问题。
两种方式中,获得数据查询的过程是不同的,第一种是无法走刚刚建立的索引,走的全表扫描,而第二种方式则可以走索引。
所以普通索引中,我们需要确认的是在条件中增加改变条件的方式,是会影响到整体的数据库查询。
上图的方式是一种解决所有查询数据结果但不在条件处加入函数的方式。
当然上面的方式也有不妥之处。最终我们还是选择函数索引,的方式来满足这样的查询方式。
从上图我们可以看到在建立了函数索引后,我们的查询已经可以走相关的索引了。
除此以外在查询中使用一些查询的方式不严谨的情况下,会导致查询数据的错误。我们可以看下面的例子
第一个查询和第二个查询后的数据结果是不一致的,第一个查询的结果要少于第二个结果,那么到底哪个是对的,我们可以分析一下, scheduled_departure 本身是一个timestamp 类型的数据,第一个查询方式中包含的数据是从2020-08-17:00:00:00 到 2020-08-17:23:59:59 秒的数据,而第二个不进行转换查询的数据是从2020-08-17 00:00:00 到 2020-08-18 23:59:59 秒的数据。其实大家也可以自己做一个这样的测试看看实际是否想上面的所说的意义。
set search_path to postgres_air; explain (verbose,analyze) SELECT * FROM flight WHERE scheduled_departure ::date BETWEEN '2020-08-17' AND '2020-08-18'; explain (verbose,analyze) SELECT * FROM flight WHERE scheduled_departure BETWEEN '2020-08-17' AND '2020-08-18';
上图为实际上我们查询中的情况,两个查询仅仅在scheduled_departure 里面进行了类型的转换,而导致两个查询的结果完全不同。
具体哪个是对的,这里并不重要,实际上我们需要理解两种查询中最终带来的结果。
而实际上我们建议大家对于这类查询的方式都不是上面的,而是下面的写法,所以针对条件字段,在大多数情况下,我们并不建议使用类型转换