优化两级SQL查询

时间:2015-08-12 12:47:25

标签: sql sqlite

以下是我数据库相关部分的布局:

database design

(顺便说一句,我用wwwsqldesigner制作了这个图表)

现在,我想查询与A的特定行匹配的所有C行。

我想出的查询是有效的。例如,在C中查找与A的第123行匹配的行:

SELECT C.* FROM C
LEFT JOIN B1 ON (B1.id = C.id_B1)
LEFT JOIN B2 ON (B2.id = C.id_B2)
WHERE B1.id_A = 123 OR B2.id_A = 123

但是,我认为上面的查询效率相当低,因为它会在大集合中收集B1和B2的所有行,然后再将其减少,对吧?

我相信我应该首先对B1和B2进行查询,选择id_A值,然后将这些结果以某种方式连接到匹配的C行。

我已经查看了sqlite.org's docs的SELECT命令,但可能性让我不堪重负。

如何解决这个问题?有点解释解决这个问题的思考过程,我们将不胜感激。

(另外,如果你能为这个问题建议一个更好的标题 - 我真的不知道如何确定这个问题)

2 个答案:

答案 0 :(得分:3)

你的方法很好,虽然好像它可能会返回重复项。

您可能会看到其中一个更快:

SELECT  C.*
FROM C
WHERE EXISTS (SELECT 1 FROM B1 WHERE B1.id = C.id_B1 AND B1.id_A = 123) OR
      EXISTS (SELECT 1 FROM B2 WHERE B2.id = C.id_B2 AND B2.id_A = 123);

这对索引最有效。 " B"中id的索引表很好,虽然(id, id_A)会更好。

OR:

SELECT DISTINCT C.*
FROM C JOIN
     B1 ON B1.id = C.id_B1
WHERE B1.id_A = 123 
UNION
SELECT DISTINCT C.*
FROM C JOIN
     B2 ON B1.id = C.id_B2
WHERE B2.id_A = 123;

如果您知道没有重复项,请使用union all代替union

答案 1 :(得分:1)

  

我认为上面的查询效率相当低,因为它会在大集合中收集B1和B2的所有行,然后再将其减少,对吧?

对于SQLite我可能是错的,但是任何有价值的数据库引擎都应该能够通过找到与B1子句匹配的B2where中的行来优化查询,所以不,它不会将整个表加载到内存中。

通过使用EXPLAIN QUERY PLAN添加查询,您可以查看查询使用的计划。只要引擎不在B1和/或B2上执行SCAN TABLE,那么查询应该没问题。

请注意,您可以通过在B1.id_AB2.id_A上添加索引来显着提高此查询的性能