Why is CKQuery so slow to download 2k records

I am running a CKQueryOperation against a the public database (in production), but it seems so slow to download the data. It's seems to take over 40seconds to download 1750 records, sometimes longer. This seems very slow to me. The records don't have any CKAssets attached to them, just 10 fields or so with basic information and one reference to another recordType.


The predicate is TRUEPREDICATE and there is no sortDescriptor set. The QOS is NSQualityOfServiceUserInteractive. I've also tried setting the "desiredKeys" property with the list of keys I want, but it doesn't make a difference. I'm afraid of how long this operation will take once there are 10,000 records. I'm not sure what else to try to make this run faster.


Here's the full code for how the operation is setup:


- (CKQueryOperation *)setupQueryOperationWithCursor:(CKQueryCursor *) cursor {

    CKQueryOperation *queryOperation = nil;
    if (cursor) {
        queryOperation = [[CKQueryOperation alloc] initWithCursor: cursor];
    }
    else {
    
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
        CKQuery *query = [[CKQuery alloc] initWithRecordType: @"InformationRecord" predicate:predicate];
        query.sortDescriptors = nil;
        queryOperation = [[CKQueryOperation alloc] initWithQuery: query];
    }

    queryOperation.container = [CKContainer containerWithIdentifier: @"BJXXXXXXX3.com.appname.icloud"];
    queryOperation.database = [queryOperation.container publicCloudDatabase];

    queryOperation.qualityOfService = NSQualityOfServiceUserInteractive;
    queryOperation.recordFetchedBlock = ^(CKRecord *record) {
        [self.allRecordsArray addObject: record];
    };
    queryOperation.queryCompletionBlock = ^(CKQueryCursor * _Nullable cursor, NSError * _Nullable operationError) {
    
        if (operationError) {
            NSLog(@“Error = %@", operationError);
        } else if (cursor) {
            NSLog(@“Query - calling again with cursor - current count = %li", self.allRecordsArray.count);
            CKQueryOperation *newQueryOperation = [self setupQueryOperationWithCursor: cursor];
            [self.operationQueue addOperation: newQueryOperation];
        } else {
            NSLog(@"Query - finished downloading data");
  }
  });
}


Is there anything I can do to make this run faster?

Replies

I am really not sure how you are able to query 2000 records at once without getting an error.


Based on my experience when I try to fetch a record set that is greater than 400, I get a limitExceeded error. I then have to split the record sets into less than 400 and try which causes more time.


If before hand you know that the result set is going to return more than 400 records, then you could fire 5 queries at the same time if there is a way to split the records. (example: Querying on a specific field which would return a record set smaller 400)


Note: In the process of the above, if you are querying on a field, then try by adding an index.



https://developer.apple.com/documentation/cloudkit/ckerror.code/1515008-limitexceeded