2011-08-12 21 views
6

Tôi có một mô hình Core Data đại diện cho một hướng dẫn viên TV trên iOS 4+, với 3 lớp:Hiệu suất: mối quan hệ Core Data được faulted sau khi được giao

  • Channel (BBC 1)
  • Program (Top Gear)
  • Broadcast (Top Gear trên BBC 1 hôm thứ Hai tại 20:00)

tôi có khoảng 40 kênh, 8000 chương trình và 6000 chương trình phát sóng, và tôi muốn tinh chỉnh im cổng quá trình để nó không mất đến một phút để chạy.

Nhập kênh và chương trình thật dễ dàng vì đây là các đối tượng độc lập. Tuy nhiên, một phát sóng có mối quan hệ với một kênh và một chương trình (1 đến nhiều người) và cả hai kênh và chương trình đều có mối quan hệ nghịch đảo với các chương trình phát sóng (nhiều-tới-1). Để tăng tốc mọi thứ, tôi có từ điển trong bộ nhớ của các kênh và chương trình lỗi chỉ có mã nhận diện Dịch vụ Web của chúng: đã tạo chương trình phát và xem qua cả hai từ điển để nhận kênh và chương trình tương ứng mà không có chuyến đi khứ hồi tới cơ sở dữ liệu.

Nhưng khi tôi chỉ định chương trình hoặc kênh phát sóng, kênh và truy cập mối quan hệ nghịch đảo của chương trình sẽ kích hoạt lỗi của cả hai đối tượng ngay lập tức, gây ra sự sụt giảm lớn (6000 * 2 yêu cầu) và áp lực bộ nhớ hậu quả như được hiển thị trong báo cáo Lỗi dữ liệu cốt lõi. Tôi đã thử tìm nạp trước mối quan hệ broadcasts trên cả hai kênh và chương trình, nhưng mối quan hệ vẫn bị lỗi.

Bạn có biết tại sao các mối quan hệ nghịch đảo bị truy cập và lỗi cha mẹ của họ không? Làm thế nào để tránh đọc từ cơ sở dữ liệu khi lưu một mối quan hệ?

CẬP NHẬT: Mã mẫu, phương pháp ấn định/cập nhật của tôi cho phiên bản Broadcast. Biến số dictionary xuất phát từ Dịch vụ web và channelsprograms chứa các kênh và chương trình lỗi được lập chỉ mục theo số nhận dạng Dịch vụ web. Lỗi xảy ra trên các dòng self.program = programself.channel = channel.

- (BOOL)assignWithDictionary:(NSDictionary *)dictionary channels:(NSDictionary *)channels programs:(NSDictionary *)programs { 
    // Add channel relationship 
    NSNumber *channelIdentifier = [dictionary objectForKey:@"channel_id"]; 

    if (self.channel == nil || ![self.channel.identifier isEqualToNumber:channelIdentifier]) { 
     Channel *channel = [channels objectForKey:channelIdentifier]; 

     if (channel == nil) { 
      NSLog(@"Broadcast %@ has invalid channel: %@", identifier, channelIdentifier); 

      return NO; 
     } 

     self.channel = channel; 
    } 

    // Same to add a program relationship 
    // ... 
} 

và Mỹ lấy yêu cầu để có được các kênh hoặc danh sách các chương trình:

- (NSDictionary *)itemsForEntity:(NSEntityDescription *)entity { 
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; 
    NSError *error = nil; 
    NSArray *itemsArray = nil; 

    request.entity = entity; 

    request.relationshipKeyPathsForPrefetching = [NSArray arrayWithObject:@"broadcasts", nil]; 
    request.propertiesToFetch = [NSArray arrayWithObjects:@"identifier", @"version", nil]; 

    itemsArray = [self.context executeFetchRequest:request error:&error]; 
    NSAssert1(error == nil, @"Could not fetch the items from the database: %@", error); 

    { 
     NSMutableDictionary *items = [NSMutableDictionary dictionaryWithCapacity:itemsArray.count]; 

     for (NSManagedObject *item in itemsArray) { 
      [items setObject:item forKey:[item valueForKey:@"identifier"]]; 
     } 

     return [NSDictionary dictionaryWithDictionary:items]; 
    } 
} 
+1

+1, bởi vì tôi đã từng có một vấn đề rất giống với vấn đề mà tôi không thể giải quyết - cuối cùng cũng làm mọi việc hoàn toàn khác. Tôi vẫn tò mò về những gì tôi có thể làm về nó, mặc dù. – Toastor

+0

Bạn "chương trình hoặc kênh phát sóng" bằng cách chỉ sử dụng "số nhận dạng"? Tôi cho rằng "số nhận dạng" là một managedObjectID hoặc một URI giống nhau? Tôi sẽ đề nghị hiển thị mã nơi bạn làm điều này. – TechZen

+0

Tôi đang nhận dữ liệu từ Dịch vụ web mô tả các mối quan hệ sử dụng số nhận dạng, không có gì liên quan đến Id dữ liệu lõi (tôi đã đề cập) – ndfred

Trả lời

1

Không chắc chắn chính xác những gì bạn đang cố gắng làm ở đây nhưng ...

Việc đầu tiên là bạn không thể thay đổi các thuộc tính chỉ bằng cách sử dụng các lỗi. Lỗi chỉ là trình giữ chỗ để cho phép bạn đo/đếm đồ thị đối tượng và các mối quan hệ đi bộ. Nếu bạn thực sự thay đổi mối quan hệ, nó sẽ kích hoạt lỗi khiến cho các đối tượng liên quan tải.

Nếu bạn đang cố gắng đặt mối quan hệ giữa các đối tượng cụ thể Channel, ProgramBroadcast chỉ sử dụng các lỗi, điều đó sẽ không hoạt động.

Phương thức itemsForEntity: Tôi không hiểu. Nó sẽ lấy tất cả các đối tượng được quản lý hiện có của thực thể được truyền và sau đó nó sẽ trả về các đối tượng đó trong một từ điển. Điều đó sẽ gây ra chi phí bộ nhớ lớn đặc biệt trong trường hợp của các đối tượng Program trong đó có 8.000 bộ nhớ.

Bạn không thể sử dụng propertiesToFetch trừ khi bạn đặt trở lại tìm nạp từ điển mà bạn không sử dụng.Tuy nhiên, bạn không thể sử dụng loại trả về từ điển nếu bạn cần đặt mối quan hệ. Bạn sử dụng cả hai khi tất cả những gì bạn muốn là dữ liệu được lưu giữ trong các thuộc tính nhất định. Nó không phải là một công cụ để thao tác các mối quan hệ của đồ thị đối tượng.

Đặt relationshipKeyPathsForPrefetching chỉ tăng tốc mọi thứ nếu bạn biết bạn sẽ truy cập vào mối quan hệ hiện có. Việc này không giúp ích gì khi bạn thiết lập các mối quan hệ ở vị trí đầu tiên, ví dụ: nếu không có đối tượng hiện có nào trong mối quan hệ broadcasts hoặc bạn đang thêm hoặc xóa Broadcast đối tượng, việc tìm nạp trước đường dẫn phím broadcasts không có gì cho bạn.

Tôi không chắc rằng tôi hiểu mô hình dữ liệu của bạn đủ tốt nhưng tôi nghĩ rằng bạn đang đi về điều này một cách sai lầm. Có vẻ như tôi đang cố gắng sử dụng identifier như một khóa chính trong cơ sở dữ liệu SQL và điều đó có thể phản tác dụng. Trong Dữ liệu cốt lõi, mối quan hệ liên kết với các đối tượng với nhau, không phải thuộc tính và giá trị được chia sẻ.

Theo quy tắc, nếu bạn có hai hoặc nhiều đối tượng có cùng tên thuộc tính có cùng giá trị, thì bạn có mô hình dữ liệu được thiết kế kém trong hầu hết các trường hợp.

+0

Cảm ơn bạn đã nhập. Kể từ iOS 4, các đối tượng dự phòng có thể được khởi tạo bằng 'propertiesToFetch' thay vì chỉ từ điển. Tôi đoán cách Core Data hoạt động, đối tượng sẽ phải bị lỗi để cập nhật mối quan hệ của họ. Tôi sẽ cố gắng làm việc độc quyền với ID đối tượng để xác nhận điều đó. Định danh là bên ngoài, tôi phải giữ nó đồng bộ với Dịch vụ Web để xử lý các bản cập nhật và phải sử dụng nó ngoài một ID đối tượng mà Core Data buộc tôi. – ndfred

+0

Tôi sẽ kiểm tra các thay đổi trong thuộc tínhToFetch, đôi khi tôi không thực hiện các thay đổi do không phải kiểm tra tài liệu quá nhiều. Không có vấn đề với việc lưu trữ một ID cho một DB bên ngoài nhưng như một quy tắc, bạn chỉ cần lưu trữ giá trị trong một thực thể. Sau đó, bạn liên kết tất cả các thực thể khác cần biết về ID cho thực thể duy nhất đó. Bạn không sử dụng cùng một giá trị thuộc tính để liên kết các đối tượng. – TechZen

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