Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS上简单(但很大)表上的Sqlite随机变慢_Ios_Ipad_Sqlite - Fatal编程技术网

iOS上简单(但很大)表上的Sqlite随机变慢

iOS上简单(但很大)表上的Sqlite随机变慢,ios,ipad,sqlite,Ios,Ipad,Sqlite,我正在为iPad开发一个企业销售应用程序,它使用Sqlite作为内部数据库,最近出现了一个奇怪的行为 我有一个巨大的表,其中充满了来自其他几个表的信息(有点像“物化视图”),它可以包含200多万行,这取决于用户的设置方式。当用户想要搜索某个项目时,应用程序会对这个包含索引列的大型表以及用作过滤器和/或元数据的其他列执行查询。我将在下面发布查询和基本想法。不管怎样,在iPad4th gen上,这个查询通常在2~3秒钟内返回,仅此而已,这很好。每当用户点击按钮将其数据与我们的服务器同步时,就会删除、

我正在为iPad开发一个企业销售应用程序,它使用Sqlite作为内部数据库,最近出现了一个奇怪的行为

我有一个巨大的表,其中充满了来自其他几个表的信息(有点像“物化视图”),它可以包含200多万行,这取决于用户的设置方式。当用户想要搜索某个项目时,应用程序会对这个包含索引列的大型表以及用作过滤器和/或元数据的其他列执行查询。我将在下面发布查询和基本想法。不管怎样,在iPad4th gen上,这个查询通常在2~3秒钟内返回,仅此而已,这很好。每当用户点击按钮将其数据与我们的服务器同步时,就会删除、重新创建和填充此表

但是,最近同一个表中的同一个查询(没有任何相关更改)随机开始需要40~50秒。如果以后在同一台设备上使用相同的筛选器(甚至更改筛选器!)执行相同的操作,那么在同一个表上执行相同的查询又需要2~3秒。我还没有发现导致这种减速的任何具体情况,该应用程序是当时唯一运行的应用程序。该设备不是问题所在,我们已经在至少5款不同的iPad上看到过这种情况,一款是iPad3,另一款是iPad4gen

我不认为这是某种缓存,因为应用程序不缓存任何东西,而且这些时间相当随机。有时他们连续10次用40秒,然后突然又开始用2秒,反过来也是一样。我唯一清楚的一点是,这种减速只有在密集使用(使用该应用程序工作1-2天)之后才会发生,因此,在我随身携带的iPad上调试时,我也遇到了导致这种行为的麻烦

我所尝试的:

  • 将仪器连接到流程,并检查减速期间使用了哪些资源。该应用程序在整个过程中都会大量使用iPad的“磁盘”(闪存)。我现在没有再分析它的例子,但我认为CPU使用率在30%左右。内存使用稳定在90~100MB,这对于我们的应用来说是正常的
  • 在db上运行真空;-例如,在我拥有的数据库上减少了~50MB。从约600MB增加到约550MB
  • 在数据库上运行分析;-没有看到任何改进
  • 在数据库上运行REINDEX;-这似乎有点帮助,但并不能解决问题
  • 终止流程并重新开始-没有任何变化
巨表的构造如下,没有任何外键或其他约束:

创建表格FMV_目录(
唯一的ID文本,
产品标识整数,

);

为查找产品而进行的查询是:

选择
产品标识
,唯一的\u ID


FMV_目录
其中
唯一的\u ID='\u'
和产品名称,如“%iPhone%”

我完全没有主意了,所以任何帮助都将不胜感激
谢谢

更新(更多信息):

我忘记提到的重要信息,罗布提醒了我。我的数据库连接始终处于打开状态,只有在用户注销时才会关闭。我们注意到,当我们保持连接打开时,应用程序的所有部分都有巨大的性能,因为我们有数百个小查询在其他情况下执行(但不是在浏览/搜索产品目录时)

用于创建索引的查询如下所示:

在MV_目录上创建索引IDX_MV_目录(唯一ID)

此外,即使列名为UNIQUE_ID,它也不是唯一的。本来应该是这样的,但现在重复了N次。我知道这是错误的,我们会尽快改变

这个“UNIQUE_ID”(不是真正唯一的)是通过连接其他两个表的ID来填充的。这样,我们的“物化视图”消除了用户在目录上搜索时至少三个连接的需要,从而将查询时间从约20秒提高到约2秒

我们不直接在查询上调用SQLITE3API,我们已经围绕它开发了一个包装类,并且我们已经使用它至少两年了。这是我们第一次遇到这种情况,但这也是我们第一次处理这么多数据。

一些想法:

  • 您没有向我们展示在
    FMV\u目录
    上创建任何索引的过程。如果没有其他内容,如果
    UNIQUE\u ID
    是唯一的(顾名思义),那么我倾向于使用
    主键定义表:

    CREATE TABLE FMV_CATALOG(
        UNIQUE_ID TEXT PRIMARY KEY,
        PRODUCT_ID INTEGER,
        <bunch of metadata/filtered columns - total of 20 columns>
    );
    
    创建表格FMV\U目录(
    唯一的\u ID文本主键,
    乘积_ID整数,
    );
    
  • 您应该尝试使用SQLite命令查看查询和它的计划,并确保它利用了您的索引。按原样执行此操作,然后再次使用
    主键
    (如果仍然无法做到这一点,请在
    WHERE
    子句中的字段上创建索引),并确保最终查询确实使用了您的索引

  • 我不知道为什么,如果你有唯一的id,为什么你还要查看其他字段。如果添加主键(可能还有其他索引)不能解决问题,我可能会尝试根据唯一id检索记录,然后检查代码中的其他参数是否一致。我不认为你需要这样做,但这是最坏的情况

  • 至于它为什么会慢下来,在没有看到代码的情况下很难猜测发生了什么(我确信这太复杂了,无法用一个简单的s.O.问题来回答)。例如,如果在一条
    sqlite3\u prepare\u v2
    语句之后,您未能完成
    sqlite3\u finalize
    ,或者您意外地未能关闭数据库,然后在其他地方再次打开它,我可以想象出奇怪的行为。我可以想象你的表演