轉: app端資料庫(效能高) realm (ios, android 均支援)

來源:互聯網
上載者:User

標籤:

轉:  http://ios.jobbole.com/85041/

 

移動端資料庫新王者:realm

2016/05/14 · iOS開發 · 資料庫

分享到:0原文出處: 沒故事的卓同學(@沒故事的卓同學)   

 

realm介紹

realm是一個跨平台移動資料庫引擎,支援iOS、OS X(Objective?C和Swift)以及Android。
2014年7月發布。由YCombinator孵化的創業團隊曆時幾年打造,是第一個專門針對移動平台設計的資料庫。目標是取代SQLite。
為了徹底解決效能問題,核心資料引擎用C++打造,並不是建立在SQLite之上的ORM。如果對資料引擎實現想深入瞭解可以查看:Realm 核心資料庫引擎探秘。因此得到的收益就是比普通的ORM要快很多,甚至比單獨無封裝的SQLite還要快。
因為是ORM,本身在設計時也針對行動裝置(iOS、Android),所以非常簡單易用,學習成本很低。

碾壓級效能

資料引自:introducing-realm
每秒能在20萬條資料中進行查詢後count的次數。realm每秒可以進行30.9次查詢後count。

 

 

在20萬條中進行一次遍曆查詢,資料和前面的count相似:realm一秒可以遍曆20萬條資料31次,而coredata只能進行兩次查詢。

 

 

這是在一次事務每秒插入資料的對比,realm每秒可以插入9.4萬條記錄,在這個比較裡純SQLite的效能最好,每秒可以插入17.8萬條記錄。然而封裝了SQLite的FMDB的成績大概是realm的一半。

 

 簡單易用

執行個體代碼語言是Objective?C。
Realm對象和其他對象沒有太大區別,只是需要繼承RLMObject

  
123456 @interface Dog : RLMObject@property NSString *name;@property NSInteger age;@end Dog *mydog = [[Dog alloc] init];

儲存起來也非常簡單,擷取資料庫執行個體,在一個事務中進行寫入。

  
12345 RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{    [realm addObject:mydog];}];

方便的查詢,可以在一個查詢結果中再進行查詢。查詢的條件有著豐富的支援。

  
1234 RLMResults *r = [Dog objectsWhere:@"age > 8"]; // Queries are chainabler = [r objectsWhere:@"name contains ‘Rex‘ AND  name BEGINSWITH ‘大‘"];

 

zero-copy和懶載入

在通常的資料庫中,資料大多數時間都靜靜地呆在硬碟當中。當你訪問 NSManagedObject 對象中的某個屬性的時候,Core Data 會將這個請求轉換為一組 SQL 陳述式,如果還未串連資料庫的話則建立一個資料庫連接,然後將這個 SQL 陳述式發送給硬碟,執行檢索,從匹配檢索的結果中讀取所有的資料,然後將它們放到記憶體當中(也就是記憶體配置)。然而,這時候你需要對其格式進行還原序列化(deserialize),因為硬碟上儲存的格式不能直接在記憶體中使用,這意味著你需要調整位,以便 CPU 能夠對其進行處理。
然而Realm跳過了整個拷貝資料到記憶體的過程,稱之為zero-copy。做到這點是因為檔案始終是記憶體映射的,無論檔案是或否在記憶體當中,你都能夠訪問檔案的任何內容。關於核心檔案格式的重要一點就是,確保硬碟上的檔案格式都是記憶體可讀的,這樣就無需執行任何還原序列化操作了。
這樣就帶來了一個問題,難道資料全載入到記憶體裡了?所以這裡懶載入應運而生,比如在查詢到一組資料後,只有當你真正訪問對象的時候才真正載入進來。

VS SQLite

SQLite第一個版本發佈於2000年,至今已16年。以當今的角度來看,它的編程抽象程度非常低。業務上我們其實只想把這些對象存進去,可以查詢出來。
即便已經是封裝過的FMDB,要寫這樣的代碼心裡也依舊難受:

  
1234567891011121314151617181920212223242526 FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];if (![db open]) {    [db release];    return;} NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"                 "create table bulktest2 (id integer primary key autoincrement, y text);"                 "create table bulktest3 (id integer primary key autoincrement, z text);"                 "insert into bulktest1 (x) values (‘XXX‘);"                 "insert into bulktest2 (y) values (‘YYY‘);"                 "insert into bulktest3 (z) values (‘ZZZ‘);"; success = [db executeStatements:sql]; sql = @"select count(*) as count from bulktest1;"       "select count(*) as count from bulktest2;"       "select count(*) as count from bulktest3;"; success = [self.db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) {    NSInteger count = [dictionary[@"count"] integerValue];    XCTAssertEqual(count, 1, @"expected one record for dictionary %@", dictionary);    return 0;}]; [db close];

 

VS CoreData

詳細的比較推薦看這篇:CoreData VS Realm。
下面給出一個查詢的比較:

  
12345678 // Core Datalet fetchRequest = NSFetchRequest(entityName: "Specimen")let predicate = NSPredicate(format: "name BEGINSWITH [c]%@", searchString)fetchRequest.predicate = predicatelet sortDescriptor = NSSortDescriptor(key: "name", ascending: true)fetchRequest.sortDescriptors = [sortDescriptor]let error = NSError()let results = managedObjectContext?.executeFetchRequest(fetchRequest, error:

Realm則簡單的多:

  
123 // Realmlet predicate = NSPredicate(format: "name BEGINSWITH [c]%@", searchString);let specimens = Specimen.objectsWithPredicate(predicate).arraySortedByProperty("name", ascending: true)

總結一下Realm對CoreData的優勢:

不需要架構Context那種煩人的東西

CoreData 是一個博大精深的技術,不要妄想幾天之內可以用的很溜。
不服看看這些書。

 

 

 

 

 

 支援 NSPredicate

從 CoreData 轉過來並沒有太多的不適應。

CoreData多個持久化檔案很麻煩,Realm輕鬆支援這個功能劣勢:

是會增加應用大概1MB的體積。CoreData原生支援,不會增加App體積。

雖然看上去很厲害,但是這麼新靠譜嗎

Realm大部分源碼公開在github上:realm。項目在建立不到兩年裡,已經得到開源社區大量關註:

 

 

官方也承諾會持續解決使用者反饋的各種問題。也可以直接在他們twitter上去@他們。

就算靠譜,有別人在用嗎

推薦閱讀這篇部落格,作者介紹了他痛下決心拋棄CoreData後,如何安全遷移至Realm:《高速公路換輪胎——為遺留系統替換資料庫》。

在多年以前,人們做了個決策,用CoreData做本機存放區,替換掉NSUserDefaults。這之間的曆史已經遠不可考,但自從我加入項目以來,整個團隊已經被它高昂的學習曲線、複雜的資料Migration流程以及過時陳舊的設計折磨的苦不堪言。於是我們決心把CoreData換掉。

文/涼粉小刀(簡書作者)
原文連結:http://www.jianshu.com/p/d684693f1d77
再看下SO的情況:

 

 

已經有大概兩萬條相關結果,你不是一個人!

需要知道的一些問題

其實我自己覺得這些是可以接受的問題。技術很多時候就是權衡,為了達到一些目的,總是要犧牲掉一些東西。

  • 所有的儲存物件需要繼承RealmObject
    比如我現在的項目的資料從網路請求回來都會繼承自己寫的一個方便解析的基類,在這裡就需要做出一些適應。
    但是該問題在swift中是不存在的。因為swift是天生的面向協議編程範式。
  • 不能自訂getter、setter
    realm會自動產生getter、setter,如果自訂getter、setter儲存就會有影響。如果要規避這個問題,可以通過設定這個對象的忽略屬性。
    比如有個屬性id,需要自訂setter。可以在對象屬性裡把id設定為忽略屬性,這樣realm就不會為它自動產生getter、setter,但是也不會把id存入資料庫。接著自訂一個用於儲存的屬性比如realm_id。在id的setter中可以把把值也賦給realm_id。
    這個問題在swift中也是不存在的,因為swfit中使用的是willset、didset這種通知機制。
  • 查詢的結果不是數組
    為了能夠支援查詢結果的鏈式查詢,realm自訂了一個集合類型。可以枚舉,但是不是熟悉的數組了。又因為realm的懶載入機制,所以不建議在資料層把這個枚舉轉成數群組類型。這樣的缺點就是上層知道了資料的儲存邏輯。嚴格的說這裡不應該讓上層知道。但是這樣設計也許是為了方便上層進行再次檢索,realm有著優越的查詢效能。

轉: app端資料庫(效能高) realm (ios, android 均支援)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.