SQLite3是否支持索引?如何加快查询速度?

时间:2013-08-31 19:13:02

标签: sql objective-c sqlite

我正在执行此查询:

NSString *querySQL = [NSString stringWithFormat:@"
        SELECT DISTINCT P1.ID_RUTA_PARADAS
        FROM FastParadas AS P1
        WHERE P1.ID_ESTACION_INIT <= %d AND
            %d <= P1.ID_ESTACION_END
        INTERSECT
        SELECT DISTINCT P2.ID_RUTA_PARADAS
        FROM FastParadas AS P2
        WHERE P2.ID_ESTACION_INIT <= %d AND
            %d <= P2.ID_ESTACION_END",
    (int)estacionOrigen.ID_Estacion,(int)estacionOrigen.ID_Estacion,
    (int)estacionDestino.ID_Estacion,(int)estacionDestino.ID_Estacion];

我想加快速度。我尝试创建一些索引,但没有任何改进。 SQLite3是否支持索引?

数据库有3900多行,此查询必须在不到一秒的时间内重复1800次以上。

3 个答案:

答案 0 :(得分:2)

  

数据库有3900多行,此查询必须重复1800+   不到一秒钟的时间。

没有。使用高度优化的扫描内存中数据的算法,不会在拥有巨大内存带宽的机器外发生。

在任何这种情况下,设计数据模型至关重要,这样就不需要这种查询。 3900多行确实不是那么多,但是对这些数据的1800多个查询是很多的。

你最好的选择是采用一种架构,不需要超过1800次查询/秒,或者最坏的情况下,设计应用程序,以便在进度条或其他内容后完成1800+查询/秒。

答案 1 :(得分:1)

除了@bbum和@ipmcc关于物理限制的观点之外,理论上你也不会有太多的运气。您要查找的是所有元组的ID_RUTA_PARADAS条目,其ID_ESTACION_INIT小于某个值,ID_ESTACION_END大于某个值(只是将其置于自然语言中)。

索引有什么用呢?

(1)假设您在ID_ESTACION_INIT上有一个支持范围查询的索引。您可以相对快速地获得满足ID_ESTACION_INIT <= %d的行的所有ID。但是你必须得到所有这些行才能找出它们是否也满足%d <= P1.ID_ESTACION_END

(2)假设您有ID_ESTACION_INIT的索引和ID_ESTACION_END两个支持范围查询的索引。然后这两个都可以获得满足谓词的所有行,并且两个索引返回的rowid可用于获取ID_RUTA_PARADA

这两种方法的问题在于,如果你想使用它们,你必须对磁盘进行随机访问,这对于小结果集只有意义(即,如果几行满足那些谓词) 。 对于更大的基数(我想我听说&gt; = 5%,但这也可能只是一个例子)你的数据库系统会去一个表扫描,以便找到所有元组,这意味着,你的索引没有帮助。

这里有一个SQLFiddle来处理索引,也可能是其他DBMS:http://sqlfiddle.com/#!5/d1a86/2

(事实上,聚集索引可以帮助阅读较少的不合格元组,但SQLite不支持它们:sqlite: Fastest way to get all rows (consecutive disk access)

答案 2 :(得分:0)

在此查询中,INTERSECT已经负责删除重复项,因此您不需要DISTINCT。以下查询可能更快:

SELECT DISTINCT ID_RUTA_PARADAS
FROM FastParadas
WHERE %d BETWEEN ID_ESTACION_INIT AND ID_ESTACION_END
  AND %d BETWEEN ID_ESTACION_INIT AND ID_ESTACION_END

但是,使用普通索引无法轻松优化此类范围查询。 您应该将数据库更改为使用一维R-tree index,在这种情况下可能有1800个查询/秒。