2016-07-06 100 views
4

比方說,我有一個CKRecordrecordType後。發佈後會保留一些值,如標題和說明。當應用程序中顯示帖子時,會附上寫它的用戶的姓名和個人資料圖片(我們稱他們爲Writer)。我的問題是 - 將CKReference存儲到Writer的配置文件(配置文件是保存Writer詳細信息的另一種類型的記錄)最好嗎?還是在寫作時直接將作者的詳細信息添加到Post中?使用CKReference與CKRecord的CloudKit性能

從數據庫模式的角度來看,第一個選項非常有意義,但從性能角度來看,它似乎非常糟糕。在這個系統中有成千上萬的用戶,提取數量和加載時間似乎都不合理。

第一部分涉及加載所有帖子。

func loadPosts() { 
    // ...Setup the query 
    publicData.performQuery(query, inZoneWithID: nil) { (results: [CKRecord]?, error: NSError?) in 
     if let posts = results { 
      self.loadProfiles(posts) 
     } 
    } 
} 

一個查詢完成,現在我們叫loadProfiles

func loadProfiles(posts: [CKRecord]) { 
    // Get the reference IDs out of the Posts 
    var referenceIDs = [CKRecordID]() 
    for post in posts { 
     // Get the reference from the post 
     // Append the recordID to the referenceIDs array 
    } 

    // Perform the Profiles fetch 
    let fetchOperation = CKFetchRecordsOperation(recordIDs: referenceIDs) 
    fetchOperation.fetchRecordsCompletionBlock = { records, error in 
     // ...Handle the fetched Profiles 

     // Everything has been fetched, update the UI now 
     dispatch_async(dispatch_get_main_queue(), { 
      self.tableView.reloadData() 
     }) 
    } 
    CKContainer.defaultContainer().publicCloudDatabase.addOperation(fetchOperation) 
} 

在該函數中,我們花費的時間抓住referenceIDs。然後,我們花時間進行配置文件提取。請注意,所有這些都是在原始的Post取回之後發生的!

...是的。即使有某種緩存系統,原始的抓取也會很瘋狂(特別是對於很多用戶)。

那麼,在他們寫作時直接將寫作者的細節添加到帖子中會更好嗎?優點:更少的抓取,更快的加載速度。缺點:如果編寫者改變他們的個人資料的詳細信息,應用程序將不得不遍歷他們的所有帖子,並手動更新細節。

這整個兩難困境挑選你的毒藥情景。有一個更好的方法嗎?

+0

我絕對建議參考,據我記錄的表現。創建某種類型的本地緩存系統,然後在它的版本與您自己的版本不同時更新每個數據並更新它,可能是通過訂閱通知。也就是說,這可能不是這個問題的最佳論壇,你可能在programmers.stackexchange.com或蘋果開發論壇上運氣更好。 –

+0

@thefredelement核心數據與某種通知來更新持久存儲是有道理的。但是,原始的抓取仍然很長。我選擇了StackOverflow而不是程序員,因爲我有代碼級別的實現。我希望有一個更好的方法來重構這個,而不必徹底改變廣泛的結構。 –

+0

查看CloudKit訂閱,您可以將一些訂閱與核心數據組合在一起,並使用提取的結果控制器來處理一個很好的解決方案。你甚至可以用後臺更新一些數據。 –

回答

5

您所描述的折衷術語是denormalization。這是你描述的困境。權衡權衡取決於底層技術以及應用領域和預期行爲。

您已經描述了兩個模型對象,一個帖子和一個配置文件,其中有一個作者對帖子上的配置文件的引用。你沒有描述它們是如何被使用的,但是我將假設它是滾動的文章列表,在表格視圖中,列表中的每個單元格上都有作者姓名和個人資料圖片。這很明顯,你爲什麼要關心每個人的引用。

CloudKit的優先事項是儘量減少往返服務器的次數。然而,一個獲取帖子和另一個獲取鏈接配置文件名稱並不是特別繁重。 非常重要:使用desiredKeys屬性獲取和查詢在這裏,當你可以。 CloudKit默認獲取整個記錄,並且您可能會通過網絡傳遞無關信息 - 這是獲取用戶名和獲取用戶完整配置文件的區別。

儘可能使用desiredKeys的要點在文檔中沒有足夠的重要性,因爲它對優化的重要性以及實現的簡單性。

但是,如果您擔心在提交帖子時發生響應,例如,如果用戶在您拉動更多時等待,您可能需要進行非規範化處理。

我也將假設一個配置文件不會經常更改 - 這是一個關鍵重點 - 但它可以改變,應用程序需要考慮這一點。這其實很簡單:在帖子中循環更新它們並不理想,但這不是什麼大不了的事情,因爲這是一個一次性的事情,你不希望經常發生。你應該可以用一對CKQueryOperation/CKModifyRecordsOperation來完成它。

再一次,一定要使用desiredKeys - 特別是如果你只是提取更新每個帖子上的非規範化字段,並不打算顯示它的任何一個,你不想傳遞全部內容電線上的每一篇文章。

請注意,如果您使用配置文件圖片進行非規範化處理,您可能需要確保您使用的是相同的CKAsset,因此您可以構建緩存,並且不會無意中上下傳送相同的圖像並存儲一堆倍。請參閱關於CKAsset和本地緩存如何工作的警告;顯然,如果你希望它保證本地存儲,你必須自己緩存它。

,這是一個好一點要注意的是,所有這些CloudKit數據類型特別是不應該被用作您的應用程序的模型對象,以及如何將與層相互作用會影響你做出任何選擇。

CloudKit實際上很棒,但在我看來,這是非系統化的文檔。今年我有幸去WWDC('16),並且能夠與一些CloudKit工程師進行交流,這些信息來自一些CloudKit工程師。希望這可以幫助。

+0

啊,哎呀,感謝偉大的的想法!我已經爲每次抓取使用'desiredKeys'。我想我應該看看CKSubscription&Core Data來作爲更新通知和持久存儲。 –

+0

@ShaanSingh CKSubscription也很棘手,Core Data是它自己的野獸。這些是應用程序設計的問題,並沒有簡單的答案。 如果這確實回答了有關困境(非規範化)的問題,那麼您是否可以將答案標記爲已接受,謝謝。 –

+1

我已經在使用核心數據NSManagedObjects來保存帖子,用戶,一切。核心數據對任何其他本機iOS緩存系統都有明顯的好處。這個答案確實有助於回答我有關非規範化的問題。謝謝。 –