0

最後の行データの読み取り後、私の sqlite3_step は 1 秒間保持されます。なんで?

-(NSDictionary*)specificationItemsForConfigurationsIds:(NSString*)configurationsIdsStr
{
    [self databaseOpen];

    NSString *query = [NSString stringWithFormat:@"SELECT SpecItem.id,SpecItem.name,ConfigurationSpec.configuration_id\
                   FROM (SpecItem INNER JOIN ConfigurationSpec ON ConfigurationSpec.spec_item_id=SpecItem.id)\
                   WHERE (SpecItem.parent_id=12 OR SpecItem.parent_id=34 OR SpecItem.id=23 OR SpecItem.id=27) AND ConfigurationSpec.configuration_id IN (%@)",configurationsIdsStr];

sqlite3_stmt *statement;

NSMutableDictionary* configurationsWithSpecItems = [NSMutableDictionary new];

if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK)
{
    while (sqlite3_step(statement) == SQLITE_ROW)
    {
        int specItemId = sqlite3_column_int(statement, 0);
        NSString* specItemName = [self sqlite3_column_text_asString_ofStatement:statement
                                                                       atColumn:1];
        int configId = sqlite3_column_int(statement, 2);
        NSString* configIdNumber = [NSString stringWithFormat:@"%d",configId];

        NSMutableArray* specItems = [configurationsWithSpecItems objectForKey:configIdNumber];
        if(specItems == nil)
        {
            specItems = [NSMutableArray new];
            [configurationsWithSpecItems setObject:specItems
                                            forKey:configIdNumber];
        }

        SpecificationItem* specItem = [SpecificationItem specificationItemWithId:specItemId
                                                                            name:specItemName];

        [specItems addObject:specItem];
        // When we read last row data, getting from here to POINT 2 takes 1s
    }
    // POINT 2
    sqlite3_finalize(statement);
}
[self databaseClose];
return configurationsWithSpecItems;
}

1 行の 1 回の読み取りには 2 ~ 3 ミリ秒かかりますが、最後に while ループから抜けると 1 秒かかります。これは私には長すぎます。

このクエリの EXPLAIN QUERY PLAN 出力:

0 0 1 SCAN TABLE Configuration (~100000 rows) 
0 0 0 EXECUTE LIST SUBQUERY 1
1 0 0 SEARCH TABLE Configuration USING AUTOMATIC COVERING INDEX (model_id=?) (~7 rows) 
0 1 0 SEARCH TABLE SpecItem USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
4

1 に答える 1

0

遅延には 2 つの説明があります。1 つまたは両方が適用される場合があります。

  • 一致するすべてのレコードがConfigurationテーブルの先頭にあります。最後に一致したレコードの後、SQLite は残りのすべてのレコードを検索する必要がありますが、一致するレコードはありません。
  • SQLite は、列に一時インデックスを作成しmodel_idます。これがないと、クエリがさらに遅くなると推定されるからです。クエリが終了したら、そのインデックスを再度削除する必要があります。表示されるのは、(自動) トランザクションの最後に同期するのに必要な時間です。

列にインデックスを作成するmodel_idと、これらの両方の点を回避するのに役立ちます。

可能であれば、( のconfigurationsIdStr) サブクエリを外側のクエリにマージするようにしてください。それ以外の:

... ConfigurationSpec.configuration_id IN (
           SELECT configuration_id FROM Configuration WHERE model_id = 42)

次のようなものを使用します。

... ConfigurationSpec.model_id = 42

その間接性を回避することで、SQLite がクエリの実行を最適化することがはるかに簡単になります。

于 2013-08-09T16:27:19.040 に答える