2011-11-19 38 views
9

Tôi đang làm việc trên ứng dụng học tập kiểu thẻ flash iOS, khi đang tải, cần lấy một loạt dữ liệu từ Dữ liệu chính. Nhưng dữ liệu tôi cần là một tập hợp con khá cụ thể của thực thể, dựa trên cài đặt người dùng, do đó, có nhiều vị từ liên quan đến việc kiểm tra tính tương đương. Tôi đang tìm thấy những tìm nạp là siêu chậm và, dựa trên nghiên cứu về SQLite, tôi nghĩ rằng một chỉ số sẽ là một lựa chọn tốt ở đây.Có thể lập chỉ mục phức tạp khi sử dụng Dữ liệu chính không?

Bây giờ, tôi hiểu (phần lớn là đọc các câu hỏi về lưu lượng truy cập stackover khác) rằng Dữ liệu SQLite và Core là hai thứ khác nhau, về cơ bản trực giao mà không nên nhầm lẫn. Nhưng nó cũng là sự hiểu biết của tôi rằng bạn đang phải làm việc thông qua Core Data để làm bất kỳ loại công việc cơ sở dữ liệu và tinh chỉnh; bạn không nên bỏ qua và làm việc trực tiếp với SQLite khi tối ưu hóa hoặc thiết kế đối tượng lâu dài trong ứng dụng của bạn.

Nhưng điều duy nhất tôi có thể tìm thấy các chỉ mục trong Dữ liệu chính là hộp kiểm "được lập chỉ mục" cho mỗi thuộc tính trong một mô hình. Và đó không phải là loại tối ưu mà tôi đang tìm kiếm.

Đây là yêu cầu lấy, hiện:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"SKUserItem" inManagedObjectContext:context]; 
fetchRequest.entity = entity; 

NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"next" ascending:YES] autorelease]; 
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; 

NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:6]; 
[predicates addObject:[NSPredicate predicateWithFormat:@"next < %f", now() + (60.0*60.0*24.0)]]; 
[predicates addObject:[NSPredicate predicateWithFormat:@"next > %f", nextOffset]]; 
[predicates addObject:[NSPredicate predicateWithFormat:@"user == %@", user]]; 
[predicates addObject:[NSPredicate predicateWithFormat:@"langRaw == %d", lang]]; 

NSArray *stylePredicates = [NSArray arrayWithObjects:[NSPredicate predicateWithFormat:@"styleRaw == %d", SK_SIMP_AND_TRAD], [NSPredicate predicateWithFormat:@"styleRaw == %d", self.style], nil]; 
[predicates addObject:[NSCompoundPredicate orPredicateWithSubpredicates:stylePredicates]]; 

if([self.parts count] == 4 || (self.lang == SK_JA && [self.parts count] == 3)) 
    ; // don't have to filter by parts; they're studying all of them 
else { 
    NSMutableArray *partPredicates = [NSMutableArray arrayWithCapacity:[self.parts count]]; 
    for(NSString *part in self.parts) 
     [partPredicates addObject:[NSPredicate predicateWithFormat:@"partRaw == %d", partCode(part)]]; 
    [predicates addObject:[NSCompoundPredicate orPredicateWithSubpredicates:partPredicates]]; 
} 

NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates]; 
fetchRequest.predicate = compoundPredicate; 

Vì vậy, về cơ bản những gì này lấy làm là sắp xếp theo tiếp theo (thời gian khi mặt hàng nhất định là do) và bộ lọc cho tên người dùng, ngôn ngữ đang được nghiên cứu, phong cách con người nghiên cứu (bằng tiếng Trung Quốc có đơn giản và truyền thống) và các phần đang được nghiên cứu (viết, giai điệu, đọc hoặc định nghĩa) và chỉ tìm nạp trong phạm vi "tiếp theo". Dưới đây là danh sách ngắn về những điều tôi đã học được từ việc chỉnh sửa và không quan tâm đến điều này:

  1. Nó luôn quét toàn bộ bảng hoặc dường như. Mặc dù tiếp theo được lập chỉ mục, ngay cả khi tôi buộc nó phải tìm kiếm một phạm vi mà tôi biết sẽ không trả về gì, nó vẫn mất vài giây để tìm nạp hoàn tất.
  2. Các biến vị ngữ, bất kỳ số lượng vị từ nào, làm cho điều này chậm. Nếu tôi loại bỏ một số nhưng không phải tất cả, nó là về chậm. Nếu tôi loại bỏ tất cả các vị từ (do đó phá vỡ các ứng dụng) sau đó nó nhanh hơn nhiều.
  3. Tốc độ phụ thuộc nhiều vào số lượng UserItems có tổng trong bảng. Càng có nhiều vật phẩm thì càng chậm. Một số người có thể có hàng chục nghìn mặt hàng và đó là khi việc tìm nạp này có thể mất tới 10 giây để hoàn thành. Điều này dẫn đến tạm dừng vụng về trong ứng dụng của tôi.
  4. Giới hạn trên của giá trị tiếp theo đã được thêm vào không phải vì chúng tôi cần nó, mà vì nó tăng tốc độ tìm nạp một chút.
  5. Có truy vấn trả về tập hợp con các thuộc tính trong từ điển (chứ không phải là toàn bộ đối tượng được quản lý) và tìm nạp phần còn lại một cách lười biếng, nhưng vẫn chưa đủ nhanh hơn.

Tôi đến từ Google App Engine ở đây, vì vậy tôi đã quen với các chỉ mục mà họ cung cấp ở đó. Về cơ bản tôi muốn loại chỉ mục đó, nhưng được áp dụng cho SQLite thông qua Core Data. Tôi tìm thấy thông tin về việc thêm các chỉ mục trong SQLite, loại mà tôi muốn, nhưng thực hiện kiểu lập chỉ mục này thông qua Core Data, tôi không thể tìm thấy bất kỳ thông tin nào về điều đó.

+0

Tôi chưa gặp sự cố về hiệu suất với Dữ liệu cốt lõi hiển thị với 1 biến vị ngữ, nhưng nếu bạn chỉ nói về hàng chục nghìn mục, bạn có thể tìm thấy hiệu suất tốt hơn bằng cách sử dụng kho dữ liệu lõi không dựa trên sql. Ví dụ, kiểu lưu trữ nhị phân có thể nhanh hơn. –

+0

Cảm ơn bạn đã đề xuất. Tôi đã thử nó nhưng nó xuất hiện, thử nghiệm trên 3GS của tôi, rằng các loại lưu trữ nhị phân không thể xử lý nhiều dữ liệu. Tôi nhận được nửa chừng tải một tài khoản với hơn 30,000 mục trước khi chương trình bị lỗi do sử dụng quá nhiều bộ nhớ. Có lẽ vì có 26 thuộc tính trong thực thể SKUserItem. –

+0

Ah, quá tệ rồi. Tôi thực sự không hiểu tại sao điểm # 1 là trường hợp nếu thuộc tính được lập chỉ mục. –

Trả lời

18

Điều bạn muốn là Chỉ mục hợp chất mà Dữ liệu chính hỗ trợ trong iOS 5.0 trở lên.

Bạn có thể thiết lập nó trong Xcode: Các Entity thanh tra có Chỉ số phần, hoặc nếu bạn đang tạo NSEntityDescription trong mã, sử dụng -setCompoundIndexes:.

Nếu bạn sử dụng Xcode, bạn muốn thêm một dòng trong Chỉ số phần đó nói

next,user,langRaw 

Bằng cách đó SQL có thể sử dụng một chỉ số cho truy vấn của bạn.

2

Dữ liệu chính có phần phụ trợ SQL. Cách bạn đã làm điều này bạn sẽ có tất cả dữ liệu trong một bảng (một phần của một thực thể) và để tìm các đối tượng bạn đang tìm kiếm sẽ yêu cầu tìm kiếm qua tất cả các hàng, như bạn nói đang xảy ra.

Trong Mô hình dữ liệu của bạn, bạn cần chia nhỏ một số thuộc tính bạn đang tìm kiếm thành các thực thể khác. Hãy thử và làm cho nó dựa trên đối tượng nhiều hơn và suy nghĩ về những gì bạn sẽ được tìm kiếm.

Ví dụ: có một thực thể cho người dùng, ngôn ngữ và có lẽ một cho bài học hoặc bất cứ điều gì dựa trên thời gian điều đó là bạn đang tìm kiếm trên.

Thực thể Bài học có mối quan hệ nhiều với Ngôn ngữ và mối quan hệ đơn với người dùng. (hoặc nhiều người dùng nếu có nhiều người dùng tham gia lớp học)

Sau đó, tìm dữ liệu của người dùng mà bạn tìm nạp người dùng đó và điều tra thuộc tính Ngôn ngữ hoặc Bài học của cô ấy để tìm hiểu thêm.

Để tìm danh sách người dùng đang nghiên cứu ngôn ngữ, tìm nạp thực thể ngôn ngữ bạn đang tìm kiếm và điều tra thuộc tính người dùng.

+0

Tôi không nghĩ rằng các mối quan hệ sẽ giải quyết vấn đề này, trừ khi tôi không hiểu khả năng của họ. Họ không phải là những bài học tôi đang tìm kiếm, nó giống như một đống thẻ flash khổng lồ. Hãy đơn giản hóa nó; nói rằng tôi chỉ muốn các lá bài Trung Quốc cho Bob, do trước đây. Nhưng cũng có thẻ tiếng Nhật cho Bob. Và thẻ Trung Quốc cho Dan. Có hàng ngàn của mỗi, và các giá trị 'tiếp theo' (do) của họ là tất cả intermingled. Nếu tôi có tất cả các thẻ liên quan đến Bob, tôi sẽ có chúng cho cả Trung Quốc và Nhật Bản. Hoặc nếu tôi có tất cả các thẻ liên quan đến Trung Quốc, tôi sẽ nhận được cả hai của Dan và Bob. Đúng? Và làm thế nào họ sẽ được sắp xếp/bị ràng buộc bởi tiếp theo? –

Các vấn đề liên quan