2013-01-04 64 views
1


我試圖執行一個查詢,它有組由子句組成。
該查詢在0.012243秒內執行
但是,當我執行[resultset next]時,首次調用時需要超過5秒。iPhone SQLite(FMDB)查詢花費時間過長

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 

我也已經能夠確定採取所有的時間是第一次[結果集下一]稱爲期間。

我還試圖修改查詢由子句通過產生UNION「編查詢像

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秒但爲[結果集所述第一呼叫下一個],時間發射到7+秒。

其他信息
表目前有8000個行,但這個數字在我的一些用戶的情況下會高達100K。

我正在使用此數據繪製特定月份銷售趨勢的圖表。

在模擬器上,該查詢執行時間少於0.5秒,但在設備上需要很長時間。

問題
你能指導我如何降低這個查詢的時間嗎?

回答

2

我下定決心,最大的瓶頸是SUBSTR集團通過條款和執行&處理類似下面只花了約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; 

我希望它可以幫助別人也陷入了類似的情況還是有些分貝大師可能會提出一些比這個醜陋的解決方案更好的選擇。