mysql/postgresql是否缓存查询的解析/编译?

8cdiaqws  于 2021-06-25  发布在  Mysql
关注(0)|答案(1)|浏览(283)

假设我在mysql(或postgresql)中执行一个查询,假设:

SELECT * FROM USER WHERE age = 20;

每次执行查询/语句时,数据库引擎是否都对其进行解析和编译?或者它是否保存了一些先前语句/查询的缓存?
如果它有一个缓存机制,它是否会对以下两个查询进行不同的处理?

/* first query */
SELECT * FROM USER WHERE age = 20 AND name = 'foo';

/* second query */
SELECT * FROM USER WHERE name = 'foo' AND age = 20;

我之所以这样问是因为我在代码中使用了一些工具来生成sql查询,这与查询中条件的顺序不一致。我只想确保这种行为不会影响我的数据库性能。
谢谢

gcmastyq

gcmastyq1#

sql是一种声明性语言,而不是过程性语言。实际执行的基本上是一个dag(有向无环图),它是一些您可能无法识别为sql构造的组件(例如“hash join”或“filter”或“sort”)。
你提到的这两个问题的条件是 name 以及 age 将编译成基本相同的编译形式。如果您有适当的索引或分区,两个查询都将使用它们。如果不这样做,那么它们可能会以不同的顺序执行布尔条件。然而,这种查询的最大开销是全表扫描,而不是单个比较。
在一些罕见的情况下,您可能需要确保条件是按特定顺序执行的——特别是如果您有一个昂贵的用户定义函数。编译器通常会为您执行此操作。如果没有,你可以使用 case 表达式:

where (case when col <> 0 then 0
            when expensive_function( . . . ) then 1
            else 0
       end) = 1

只有当 col = 0 ,因为 case 表达式按顺序计算其表达式(在非聚合查询中)。
至于缓存,这取决于服务器和选项。一般来说,数据库缓存查询计划,因此它们不需要重新编译。这通常是在准备好的语句级别,而不是查询的文本。数据库通常不会缓存结果,因为基础表中的数据可能会更改。

相关问题