2010-11-15 216 views
5

如果你有一个查询,如:SQLite的连接优化

select a.Name, a.Description from a 
inner join b on a.id1 = b.id1 
inner join c on b.id2 = c.id2 
group by a.Name, a.Description 

什么是索引最优化的列此查询SQLite中,如果你认为有超过10万行的每个表?

,我想问的原因是,我没有得到与由我希望从另一个RDBMS(SQL Server)的,当我采用同样的优化与该组的查询性能。

我会是正确的思维,在SQLite的查询中的单个表引用的所有列必须列入最佳性能单一的综合指数?

+2

我的内心灵变态是抽搐的事实,你有一个group by子句没有任何聚合函数(S)。你想通过团队达成什么目标? – 2010-11-15 13:24:05

+1

@MyOtherMe:看到我下面的答案,我想他想要的是在b和c表中引用的所有描述和名称。 – MPelletier 2010-11-15 13:27:45

+0

那正是我所追求的。 – gmn 2010-11-22 09:28:42

回答

4

的问题是,你希望的SQLite具有相同的性能作为一个完整的RDBMS。它不会。 SQLLite在内存中没有足够的缓存空间,每次运行应用程序时都必须重新构建缓存,可能仅限于设置内核数量等,等等。使用嵌入式RDBMS的权衡超过一个完整的。

只要优化进行,请尝试索引查找列并进行测试。然后尝试创建一个覆盖索引。一定要测试selects和更新数据库的代码路径,你会以牺牲另一个为代价加快速度。找到适合您需求的两种最佳平衡的索引,并与之配合。

+0

感谢您的回答,我以前曾尝试在a.Id1,a.name,a.description以及b.id1,b.id2和c.id2上的另一个索引上添加一个复合索引。但是,这些都没有帮助该团队的表现。这是什么引发了这个问题,因为在这种情况下,使用SQLite似乎不可能通过性能获得足够的分组。我想这只是拥有嵌入式数据库的限制之一。 – gmn 2010-11-22 09:41:03

1

请注意:我什么都不知道SQLite和它的执行计划可能错综复杂。

您绝对需要索引a.id1,b.id1,b.id2c.id2。我认为一个综合指数(b.id1, b.id2)可以产生一个小的性能增加。 (a.id1, a.Name, a.Description)也是如此。

2

SQLite query optimization overview

当执行行的索引查找,通常的程序是做对指数的二进制搜索来查找索引项,然后提取从索引和使用ROWID是rowid在原始表上执行二进制搜索。因此,典型的索引查找包含两个二进制搜索。但是,如果从表中提取的所有列在索引中已经可用,则SQLite将使用索引中包含的值,并且永远不会查找原始表格行。这为每行节省了一次二进制搜索,并且可以使许多查询以两倍的速度运行。

对于任何其他RDBMS,我会说把一个聚集索引上b.id1和c.id2。对于SQLite,你可能会更好,包括你想在这些索引中查找的b和c中的任何列。

+0

覆盖索引几乎存在于每个RDBMS中,并且对查找具有相同的效果。问题是大型索引会影响插入/更新性能,所以您必须在更新性能和选择性能之间进行权衡。 – Donnie 2010-11-15 13:16:00

+0

感谢您的回复,请原谅我的无知,但是您是否声称可以在SQLite中创建包含多个表中的列的索引,类似于SQLServer中的索引视图? – gmn 2010-11-22 09:43:40

+1

嗯,我在说当你在B上创建索引时,不要只在B.id上创建索引,而是在索引中包含你需要从B中获得的所有数据列。这将为您节省一个二进制搜索这些数据列。在另一个DBMS中,通过在索引中包含来自多个表的列可能会更快,但SQLite并没有那么先进。 – thomaspaulb 2010-11-23 10:40:55

0

既然你不使用你的归来列的其它表,这也许会更快:

SELECT DISTINCT a.Name, a.Description 
FROM a, b, c 
WHERE a.id1 = b.id1 
AND b.id2 = c.id2 

望着返回的列,因为该标准似乎只有他们必须从被链接abc,你可以看看所有独特的a.Namea.Description对。

SELECT DISTINCT a.Name, a.Description 
FROM a 
WHERE a.id1 IN (
SELECT b.id1 
FROM b 
WHERE b.id2 IN (
    SELECT c.id2 
    FROM c 
) 
) 

,或者取决于如果每对a.Namea.Description已经是独一无二的,应该是在找出第一个唯一的ID的获取,然后其他列一定的增益。

SELECT a.Name, a.Description 
FROM a 
WHERE a.id1 IN (
SELECT DISTINCT a.id1 
FROM a 
WHERE a.id1 IN (
    SELECT b.id1 
    FROM b 
    WHERE b.id2 IN (
    SELECT c.id2 
    FROM c 
    ) 
) 
) 
1

我认为a.id1和b.id2指标会给你有关,你可以在这些连接方面得到尽可能多的好处。但SQLite提供了EXPLAIN,它可以帮助您确定当前执行计划中的效率是否可以避免。