1


group by句を 含むクエリを実行しようとしています。
クエリは 0.012243 秒で実行されますが、[resultset next]
を実行すると、最初に呼び出されるときに 5 秒以上かかります。

NSMutableArray *recordsArray = [[NSMutableArray alloc] init];

NSString * query = @"select count(id), SUBSTR(purchase_date, 0,11) as purchase_date from sales where purchase_date LIKE '2012-12%' group by purchase_date order by purchase_date asc";

NSDate * date1 = [NSDate date];

FMResultSet * resultset = [database executeQuery:query];

NSDate * date2 = [NSDate date];
NSTimeInterval timeTaken = [date2 timeIntervalSinceDate:date1];
NSLog(@"TimeTaken: %f", timeTaken);     //outputs around 0.012


while ([resultset next])
{
    [recordsArray addObject:[resultset resultDictionary]];
}

date2 = [NSDate date];      
timeTaken = [date2 timeIntervalSinceDate:date1];
NSLog(@"TimeTaken 2: %f", timeTaken);   //outputs around 5.5 seconds

また、かかった時間はすべて[resultset next]が最初に呼び出されたときであると判断できました。

また、次のようなUNIONのクエリを生成することにより、クエリを変更してgroup by句を削除しようとしました

NSString * query2 = @"select * from 
(
    select count(id), SUBSTR(purchase_date, 0,11) as purchase_date from sales where purchase_date = 2012-12-01
    UNION
    select count(id), SUBSTR(purchase_date, 0,11) as purchase_date from sales where purchase_date = 2012-12-02
    UNION
    select count(id), SUBSTR(purchase_date, 0,11) as purchase_date from sales where purchase_date = 2012-12-03
    ....
    UNION
    select count(id), SUBSTR(purchase_date, 0,11) as purchase_date from sales where purchase_date = 2012-12-31
) where purcase_date is not NULL order by purchase_date asc";

このクエリの実行にも 0.2 秒かかりますが、[resultset next] への最初の呼び出しと時間は 7 秒以上かかります。

その他の情報
テーブルには現在 8000 行以上ありますが、一部のユーザーの場合、その数は 100K に達する可能性があります。

このデータを使用して、特定の月の売上傾向のグラフをプロットしています。

シミュレーターでは、このクエリは 0.5 秒未満で実行されますが、デバイスではかなりの時間がかかります。

質問
このクエリの時間を短縮する方法を教えてもらえますか?

4

1 に答える 1

2

最大のボトルネックはSUBSTR句とGroup By句であると判断し、次のような単純なクエリの実行と処理には約 0.02 秒しかかかりませんでした

Select purchase_date from sales where purchase_date LIKE '2012-12%' order by purchase_date asc;

そこでインナークエリとして導入しました

Select count(purcahse_date) as count, SUBSTR(purchase_date, 0, 11) as purchase_date from
(
    Select purchase_date from sales where purchase_date LIKE '2012-12%'
)
group by purchase_date, order by purchase_date;

生成されたデータは最初のクエリと同じでしたが、時間は以前と同じように約 5.5 秒に急上昇しました。

最終的な解決策は、特定の月のすべての purchase_date レコードを取得し、それらを自分で処理することです。

だから今、コードは次のようになります

while ([resultset next])
{
    [recordsArray addObject:[resultset resultDictionary]];
}
[resultset close];

[self closeDB];
        //release the db lock at this point

int array[31];    //maximum days in a month
bzero((void *)array, 31 * sizeof(int));     //initialize the month array

for(NSDictionary * d in recordsArray)    //read the records received from the db and add daily sales count
{
    NSRange r;
    r.location = 8;
    r.length = 2;
    int dDate = [[[d objectForKey:@"purchase_date"] substringWithRange:r] intValue];
    array[dDate-1]++;
}

[recordsArray removeAllObjects];

//refDate contains @"2012-12"
for(int i=0; i<31; i++)     //now populate the final array again
{
    if(array[i] > 0)
    {
        NSDictionary * d1 = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%@-%02d", refDate, i+1], @"date", [NSNumber numberWithInt:array[i]], @"count", nil];
        [recordsArray addObject:d1];
    }
}

return recordsArray;

他の誰かが同様の状況で立ち往生するのに役立つことを願っています。または、一部のデータベースの第一人者が、この醜いソリューションよりも優れた代替案を提案する可能性があります。

于 2013-01-04T16:16:45.763 に答える