我有两个表,一个名为 Health_User ,另一个名为 Diary 。它们分别具有用户的人口统计信息和记录值。我想要做的是检索记录的值,但是:
所以我有几个查询应该得到相同的结果:
# Query 1
SELECT d.user_id, d.id AS diary_id, d.glucose_value, d.unit
FROM Diary AS d
JOIN (
SELECT id
FROM Health_User
WHERE is_tester = false
) AS u
ON d.user_id = u.id
WHERE ((d.glucose_value >= 20 AND d.glucose_value <= 600 AND d.unit = 'mg/dL')
OR (d.glucose_value >= 20/18.02 AND d.glucose_value <= 600/18.02 AND d.unit = 'mmol/L'));
# Query 2
SELECT d.user_id, d.id AS diary_id, d.glucose_value, d.unit
FROM Diary AS d
JOIN Health_User AS u
ON d.user_id = u.id
WHERE u.is_tester = false
AND ((d.glucose_value >= 20 AND d.glucose_value <= 600 AND d.unit = 'mg/dL')
OR (d.glucose_value >= 20/18.02 AND d.glucose_value <= 600/18.02 AND d.unit = 'mmol/L'));
# Query 3
SELECT d.user_id, d.id AS diary_id, d.glucose_value, d.unit
FROM Health_User AS u
JOIN (
SELECT id, user_id, glucose_value, unit
FROM Diary
WHERE ((glucose_value >= 20 AND glucose_value <= 600 AND unit = 'mg/dL')
OR (glucose_value >= 20/18.02 AND glucose_value <= 600/18.02 AND unit = 'mmol/L'))
) AS d
ON d.user_id = u.id
WHERE u.is_tester = false;
这里我有三个问题:
问题1:我推测查询1的性能优于查询2,因为a)它只加入一列而不是 Health_User 的整个表格,b)它之前过滤掉了测试人员加入表格。我是对的吗?
问题2: Diary 的条件限制更复杂(请参阅查询1中的最后一个WHERE
子句)。是否最好在JOIN
内切换日记,并在查询3之外点击 Health_User ,否则没有区别?
问题3:在性能方面是否有更好的解决方案?
答案 0 :(得分:0)
如果数据库按照您的查询建议的顺序执行查询(首先过滤,然后加入,反之亦然),则会有所不同。
实际上,PostgreSQL有一个查询优化器,可以重新排列查询以找到最有效的执行顺序,并且所有查询最终都会使用相同的执行计划 ,您可以使用SQL语句EXPLAIN
验证。
对于内连接,如果在连接之前或之后进行过滤,则不会影响结果;您也可以将所有条件写入连接条件而不更改结果。优化器知道这一点。
您可以通过创建适当的索引来加快执行速度。它取决于数据的分布,以了解某个索引是否有用。经验法则是选择条件下的索引(过滤掉许多数据)更有用。使用EXPLAIN
查找最佳索引。