【问题标题】:iPhone Sqlite Performance ProblemiPhone Sqlite 性能问题
【发布时间】:2009-07-25 09:07:13
【问题描述】:

大家好,这里是最底层的。

我有一个表,由主键(col1)、文本(col2)和文本(col3)组成。基本上是一张地图。该表包含大约 200k 行。检索一行基本上需要大约 1.x 秒(这就是我想要的)。我基本上使用 select * from table where col2 = 'some value'。

我尝试为所有三列、每一列以及 col2 和 col3 创建一个索引,但这并没有改善我的情况。

我在想,这正常吗?我没有遇到任何人抱怨大型表的sqlite性能缓慢的帖子,所以我想知道我做错了什么。

任何帮助将不胜感激。

【问题讨论】:

  • 你确定只有一行是结果吗?
  • 另外,我建议在运行查询时针对您的应用程序运行 Instruments 或 Shark。我有一个类似的问题,并认为它是 SQLite,但事实证明它是我的代码中导致速度变慢的次优字符串解析方法。
  • 是的,我确定只返回一行,我会试试鲨鱼,谢谢你的想法!

标签: iphone sqlite


【解决方案1】:

我会说,这绝对不是典型的。

即使您有一个大表,通过索引进行访问也应该相当快。

你能做什么:在 col2 上只创建一个索引(这是你唯一需要的这个选择!)。

比起使用“EXPLAIN SELECT ....”来获取信息,SQLite 从中得到了什么。结果不容易看懂,不过有一些经验还是可以看一下是否使用了索引。您也可以在此处发布结果。

【讨论】:

  • 这是解释 select * from table where col1 = 'something' 0|Goto|0|23| 的输出1|整数|0|0| 2|打开读取|0|2| 3|SetNumColumns|0|3| 4|整数|0|0| 5|OpenRead|1|4|keyinfo(1,BINARY) 6|String8|0|0|one 7|IsNull|-1|20| 8|制作记录|1|0|a 9|MemStore|0|0| 10|移动锗|1|20| 11|内存加载|0|0| 12|IdxGE|1|20|+ 13|IdxRowid|1|0| 14|移动锗|0|0| 15|列|0|0| 16|列|0|1| 17|列|0|2| 18|回调|3|0| 19|下一个|1|11| 20|关闭|0|0| 21|关闭|1|0| 22|暂停|0|0| 23|交易|0|0| 24|验证Cookie|0|3| 25|转到|0|1| 26|Noop|0|0|
  • 嗨,保罗,如何将其粘贴到您的原始帖子(当然也可以是答案)中,每个前导空白有 4 个(这对于编码来说是特殊的)。因此它不会过期。
  • 据我所知,使用了索引。但它接缝你的问题是我从其他帖子中看到的开发系统。所以这个问题应该解决了。
【解决方案2】:

我解决了这个问题。那是当我创建一个新的 sqlite 数据库文件并将其添加到项目中时,xcode 没有正确重新编译自身,它仍在使用旧文件。我不得不从项目中删除旧数据库,删除计算机上的编译版本,清理项目,然后编译它并确保它由于数据库丢失而崩溃。然后再次删除编译的文件,清理它,并重新添加新的 sqlite 数据库。

这就是为什么即使在我创建索引之后,性能也没有任何提升......

奇怪,这会被认为是 Xcode 的错误吗?

【讨论】:

    【解决方案3】:

    我已经把这个类变成了一个单例(称为 SQLAdapter),它在这里包含两个方法,一个用于在需要时复制数据库,另一个用于执行我的 sql 代码:

    这里是sql代码方法,这是我第一次用Obj-C编码,所以忽略字符串追加方法,我正在改变这个,我们说话......

    - (NSString *)getMapping:(NSString *)test{
        //Our return string
        NSString *res = test;
    
        // Setup the database object
        sqlite3 *database;
    
         NSString *sqlStmnt;
         if (direction) sqlStmnt = @"select * from table where col1 = '";
         else sqlStmnt = @"select * from table where col2 = '";
    
         NSString *tStmt = [sqlStmnt stringByAppendingString:test];
         NSString *sqlState = [tStmt stringByAppendingString:@"'"];
         const char * sqlStatement = [sqlState UTF8String];
    
        // Open the database from the users filessytem
        if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
            // Setup the SQL Statement and compile it for faster access
            sqlite3_stmt *compiledStatement;
            //execute the statement
            if (sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) != SQLITE_OK) {
                NSAssert1(0, @"Error: during prepare '%s'.", sqlite3_errmsg(database));
            }
            //bind our translation into the sql select statment 
            sqlite3_bind_text( compiledStatement, 1 , [word UTF8String], -1, SQLITE_TRANSIENT);
            if(sqlite3_step(compiledStatement) == SQLITE_ROW) { //if execution is successful i.e. we get a match
                //lets return the desired language translation
                res = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, (direction) ? 2 : 1)];
            }
            sqlite3_finalize(compiledStatement);    //Release the compiled statement from memory
        }
        sqlite3_close(database);    //lets return the translation
        return res;
    }
    

    如果我没记错的话,与 SQLiteBooks 项目的做法几乎完全相同......

    【讨论】:

    • 废话,格式搞砸了,这里的格式很好:dpaste.com/71397
    • 所以我移动了每次我想执行查询时打开数据库的代码,以便在程序第一次加载时打开数据库,然后我只执行查询。瓶颈似乎与 sqlte3_step(stmt) 有关。这绝对是所有事情中时间最长的。
    猜你喜欢
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多