2012-05-01 25 views
7

Tôi đang phân tích cú pháp dữ liệu mà ban đầu tôi chèn vào kho lưu trữ dữ liệu cốt lõi.Cải thiện tốc độ cập nhật bản ghi hiện có (~ 11.000) trong Dữ liệu chính

Tại thời điểm sau, tôi phân tích cú pháp cùng một XML, mặc dù một số trong số đó là có thể đã được cập nhật. Những gì tôi làm sau đó là kiểm tra bản ghi hiện có với cùng một thẻ và nếu một thẻ đã tồn tại, tôi cập nhật bản ghi với dữ liệu.

Tuy nhiên, trong khi phân tích ban đầu của tôi (khoảng 11.000 bản ghi) mất 8 giây hoặc lâu hơn, việc cập nhật có vẻ tốn kém và mất 144 giây (đây là Simulator chạy, lâu hơn đáng kể trên thiết bị thực).

Khi lần đầu tiên ổn (tôi đang hiển thị thanh tiến trình), cột thứ hai không thể chấp nhận được và tôi muốn làm gì đó để cải thiện tốc độ (mặc dù nó xảy ra ở nền trên một sợi riêng biệt) .

Thật không may, nó không phải là vấn đề của find-or-create vì dữ liệu trong XML có thể đã thay đổi cho từng bản ghi, vì vậy, về cơ bản, mỗi bản cập nhật có thể cần.

Tôi đã lập chỉ mục các thuộc tính, tăng tốc phân tích ban đầu và cập nhật, nhưng vẫn chậm (các số ở trên có lập chỉ mục). Những gì tôi đã nhận thấy rằng việc phân tích/cập nhật dường như chậm dần. Trong khi ban đầu nhanh, nó trở nên chậm hơn và chậm hơn vì ngày càng nhiều bản ghi được xử lý.

Vì vậy, cuối cùng câu hỏi của tôi là liệu có bất kỳ đề xuất nào cho tôi về cách tôi có thể cải thiện tốc độ mà tôi đang cập nhật tập dữ liệu của mình không? Tôi đang sử dụng MagicalRecord để tìm nạp bản ghi. Đây là mã:

Record *record; 
if (!isUpdate) { 
    record = [NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:backgroundContext]; 
} else { 
    NSPredicate *recordPredicate = [NSPredicate predicateWithFormat:@"SELF.tag == %@", [[node attributeForName:@"tag"] stringValue]]; 
    record = [Record findFirstWithPredicate:recordPredicate]; 
} 
+0

tần suất bạn gọi là lưu trên Bối cảnh? –

+0

Tôi gọi tổng cộng 18 lần. Tôi đã chơi xung quanh với con số này và nó có vẻ là số ma thuật cho tốc độ tổng thể. – runmad

+0

Nếu tôi đọc chính xác, lần đầu tiên bạn chèn các bản ghi này, nó chỉ mất khoảng 8 giây. Vì vậy, nó là ngây thơ để tin rằng nếu bạn xóa các thực thể hiện có sau đó chèn một cái mới với các dữ liệu cập nhật rằng nó sẽ được nhanh hơn? –

Trả lời

3

Thay vì thực hiện tấn tìm nạp, hãy thực hiện một truy vấn cho từng loại thực thể và lưu trữ chúng trong từ điển theo thẻ, sau đó chỉ cần kiểm tra từ điển nếu có đối tượng có khóa đó. Bạn sẽ có thể đặt propertiesToFetch để chỉ bao gồm thẻ và nó sẽ giảm chi phí.

+0

Đó chính xác là cách tiếp cận của tôi, tôi không hiểu tại sao tìm hoặc tạo không quan trọng ở đây, đúng không -create áp dụng? – codeclash

+0

Không, không phải vậy. Find- * hoặc * -treate vấn đề nếu bạn cần chèn một bản ghi hoàn chỉnh không tồn tại. Trong trường hợp của tôi, tôi cần cập nhật hồ sơ nếu cần. Vì vậy, tôi sẽ cần phải chèn một bản ghi mới nếu nguồn cấp dữ liệu XML có một bản ghi mới, nhưng đối với mỗi bản ghi đã có trong cơ sở dữ liệu, tôi cần phải cập nhật các thuộc tính của nó. – runmad

+0

Hãy kiểm tra lại: Có đúng là mỗi mục trong xml mới của bạn, bạn lấy "Thẻ", thực hiện yêu cầu tìm nạp trên tất cả các mục trong kho dữ liệu cốt lõi để kiểm tra xem có tồn tại một mục như vậy không, nếu có, cập nhật một, nếu không, chèn? Không phải là nó sau đó đúng là bạn về cơ bản làm một yêu cầu lấy cho M EI mục trong XML tươi của bạn? Nếu vậy, bạn chắc chắn muốn chỉ làm một lần tìm nạp (để lấy NSDictionary (key = "Tag", value = Item) của TẤT CẢ các mục hiện có trong cửa hàng liên tục, và tra cứu NSDictionary cho những cái hiện có (và cập nhật chúng, làm tiết kiệm theo lô) và chèn những cái mới chỉ khi không tìm thấy? – codeclash

1

Một điều bạn có thể thử sẽ sử dụng mẫu NSPredicate để bạn không phân tích lại chuỗi định dạng cho mỗi lần tìm/tìm nạp mà bạn đang thực hiện.

Vì vậy, trước khi bạn nhập vòng lặp của bạn:

NSPredicate *template = [NSPredicate predicateWithFormat:@"SELF.tag == $RECORD_TAG"]; 

bên trong vòng lặp:

Record *record; 
if (!isUpdate) { 
    record = [NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:backgroundContext]; 
} else { 
    NSPredicate *recordPredicate = []; 
    record = [Record findFirstWithPredicate:[template predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:[[node attributeForName:@"tag"] stringValue] forKey:@"RECORD_TAG"]]; 
} 

See Predicate Programming Guide để biết thêm Apple.

+0

Giúp một chút. Tôi đã thực sự làm điều này cho ~ 98% của các đối tượng (có nhiều loại), và bây giờ làm nó với phần còn lại. Đã lưu tôi khoảng 2 giây trong số 144 giây cho đến thời điểm này :) – runmad

1

Bạn cũng có thể thử kết hợp câu trả lời của Người cao tuổi với băm thuộc tính.

Khi chèn băm các thuộc tính và lưu trữ băm đó dưới dạng một thuộc tính kiểm tra của Record.
Khi cập nhật, bạn đặt các thuộc tính đã tìm nạp thành thẻ và tổng kiểm tra và thực hiện một lần tìm nạp tất cả các mục. Sau đó, khi bạn lặp qua tập dữ liệu của mình nếu tổng kiểm tra khác với dữ liệu đã được tìm nạp, bạn có thể tìm nạp Record và cập nhật nó.

1

Câu trả lời ban đầu cho TẤT CẢ các vấn đề về hiệu suất là chạy các công cụ. Sau đó, với dữ liệu đó, bạn có thể xác định các khu vực sự cố của mình. Từ đó, bạn có thể có các câu hỏi khác, cụ thể, về các khía cạnh nhất định trong việc cải thiện hiệu suất.

Con người chúng tôi nổi tiếng là xấu khi xác định các tắc nghẽn hiệu suất. Vì vậy, sử dụng các công cụ đầu tiên. Nó chắc chắn sẽ cho bạn biết thời gian của bạn đang được chi tiêu.

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