Realm从入门到放弃(一)

作者: heweiming 分类: iOS,干货 发布时间: 2016-12-08 23:07

Realm从入门到放弃(一)

最近Realm的确比较火,火是因为它的速度,更因为它是一个比较完善的对象存储方案。当然最最最重要的是它有中文的文档,所以在我大天朝也有不少的猿类在使用这款数据库。

介绍

Realm 是一个跨平台的数据库引擎,为了彻底解决性能问题,Realm并不是在SQLite之上进行开发的ORM,而是由C++打造的一套全新的引擎。因此它的性能比普通的ORM要快很多,在某些方面比SQLite还要快。

Realm 目前支持的语言有Objective-C、Swift、Java、JavaScript跟Xamarin。看上去是移动端的份额比较多。

因为是ORM,所以本身也是为了取代SQLite而存在的一套引擎,设计时也是专门针对移动设备(iOS、Android),学习成本比较低,不过由于Realm本身对数据处理这一块是比较弱的,例如 limit 这个在SQL语句中经常用到的用来分页的功能,在Realm中是没有的,只能通过对应的操作自己的限制数量。

一、性能

评价:碾压级 数据来自 Realm的官方介绍
cout对比图

该图是20万条数据中进行查询并且count。而Realm可以每秒进行30.9次查询并且count。这数据在主流的移动数据库中不可谓不逆天。



queries对比图

有了count怎么可能没有queries,Realm在queries中跟count的数据几乎是一样的。也是跟其他主流移动数据中拉了很大的差距。



Inserts对比图

Inserts对比中可以发现Sqlite的速度终于领先了Realm,不过原因,我猜应该是线程安全的问题。而同样是主流的基于Sqlite封装的FMDB性能竟然是原生的四分之一,是Realm的二分之一。

今天先说我比较熟悉的Objective-C好了

首先我们来看一下 Realm 的官网。Realm 一眼看上起全是英文,不过呢,在网站的右上角有个小地球,只需要稍微切换一下,就立刻回到我大天朝时代了。不过身为猿类,学会并且习惯看英文文档是一个很重要的技能。

二、易用性

评价:友好 数据来自:Realm-Objc官方文档

说是友好是因为Realm提供了中文文档,虽然中文文档不是最新的,但是足够我们进坑和爬坑用了。

不过要说的一个点是Realm的代码入侵性比较强,如果不是全新的项目而是老项目,要转过来要慎重考虑。还有Realm是没有多表查询这个说法的,也没有连表的说法,所以如果你的客户端逻辑比较复杂,我建议还是不要用Realm。

Realm 的用法很简单,其实只需要把你需要存储的模型(NSObject)继承RLMObject。如果是新项目的话这个是没问题的,但是如果是老项目,已经用其他数据库做了大量的存储的话。那就得花一点时间了把模型改过来了。模型里面如果有NSMutableArray或者NSArray的属性,那就得改成RLMArray并且在属性接口文件end后面加上RLM_ARRAY_TYPE(ModelName)才可以。

范例:

#import <Realm/Realm.h>

@class Person;

// Dog model
@interface Dog : RLMObject
@property NSString *name;
@property Person   *owner;
@end
RLM_ARRAY_TYPE(Dog) // define RLMArray<Dog>

// Person model
@interface Person : RLMObject
@property NSString             *name;
@property NSDate               *birthdate;
@property RLMArray<Dog *><Dog> *dogs;
@end
RLM_ARRAY_TYPE(Person) // define RLMArray<Person>

// Implementations
@implementation Dog
@end // none needed

@implementation Person
@end // none needed

Realm支持的数据类型有:BOOL, bool, int, NSInteger, long, long long, float, double, NSString, NSDate, NSData, and NSNumber。

三、工具

评价:精致 数据来自:Realm-Objc官方文档

Realm 提供一个很棒的MAC上的数据库浏览工具叫做 Realm Browser。这个数据浏览器可以承担阅读与修改Realm产生的数据库文件 .realm。而且它有一个很好的特性,如果你已经用RealmBrowser打开了数据库文件,无论你的数据怎么改,你重新run一次代码,Realm Broswer是可以即时捕捉,并且不用重新找到沙盒再找到.realm然后重新打开。

Realm Browser

Realm 还进行了大部分的开源,如果有兴趣的人可以去参考一下github

Realm 除了提供使用文档,还提供了API文档

四、功能性

评价:3星 数据来自:Realm-Objc官方文档

数据库这种比较核心的东西,不是说随便想换就换,所以得有几个维度去考虑这些问题:

1.性能必须得比目前的高

2.数据迁移比较简单

3.有完善的文档与API

4.代码入侵性不高

下面来看一下Realm到底有什么功能:


索引属性(Indexed Properties)


重写 +indexedProperties 方法可以为数据模型中需要添加索引的属性建立索引:

@interface Book : RLMObject
@property float price;
@property NSString *title;
@end

@implementation Book
+ (NSArray *)indexedProperties {
  return @[@"title"];
}
@end

Realm 支持字符串、整数、布尔值以及 NSDate 属性作为索引。

对属性进行索引可以减少插入操作的性能耗费,加快比较检索的速度(比如说 = 以及 IN 操作符)。

属性默认值


重写+defaultPropertyValues 可以每次在对象创建之后为其提供默认值。

@interface Book : RLMObject
@property float price;
@property NSString *title;
@end

@implementation Book
+ (NSDictionary *)defaultPropertyValues {
    return @{@"price" : @0, @"title": @""};
}
@end

对象的自更新特性

RLMObject 实例是底层数据的动态表现,其会进行自动更新,这意味着对象不需要进行刷新。修改某个对象的属性会立刻影响到其他所有指向同一个对象的实例。

Dog *myDog = [[Dog alloc] init];
myDog.name = @"小白";
myDog.age = 1;

[realm transactionWithBlock:^{
  [realm addObject:myDog];
}];

Dog *myPuppy = [[Dog objectsWhere:@"age == 1"] firstObject];
[realm transactionWithBlock:^{
  myPuppy.age = 2;
}];

myDog.age; // => 2

RLMObject 的这个特性不仅让 Realm 保证速度和效率,它同时还让代码更加简洁、更为灵活。比如说,如果您的 UI 代码是基于某个特定的 Realm 对象来现实的,那么在触发 UI 重绘之前,您不用担心数据的刷新或者重新检索等问题。

主键(Primary Keys)

重写 +primaryKey 可以设置模型的主键。声明主键之后,对象将允许进行查询,并且更新速度更加高效,而这也会要求每个对象保持唯一性。 一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。

@interface Person : RLMObject
@property NSInteger id;
@property NSString *name;
@end

@implementation Person
+ (NSString *)primaryKey {
    return @"id";
}
@end

忽略属性(Ignored Properties)

重写 +ignoredProperties 可以防止 Realm 存储数据模型的某个属性。Realm 将不会干涉这些属性的常规操作,它们将由成员变量(ivar)提供支持,并且您能够轻易重写它们的 setter 和 getter。

@interface Person : RLMObject
@property NSInteger tmpID;
@property (readonly) NSString *name; // 只读属性将被自动忽略
@property NSString *firstName;
@property NSString *lastName;
@end

@implementation Person
+ (NSArray *)ignoredProperties {
    return @[@"tmpID"];
}
- (NSString *)name {
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
@end

忽略属性的行为与 Objective-C 或者 Swift 类当中的普通对象相似。它们并不支持任何一种 Realm 特定的功能。例如,无法通过查询来检索忽略属性,也无法实现自动更新,即便另一个相同对象的实例的忽略属性值发生了变更。此外忽略属性发生更改的时候也不会触发通知,尽管仍然可以使用 KVO 来实现简直观察。

可空属性(Optional Properties)

通常情况下,NSString 、NSData 以及 NSDate * 属性可以设置为 nil。如果你不需要实现此功能,你可以重写您的 RLMObject 子类的 +requiredProperties 方法。

比如对于以下的模型定义来说,如果尝试给 name 属性设置为 nil 将会抛出一个异常,但是将 birthday 属性设置为 nil 却是允许的:

@interface Person : RLMObject
@property NSString *name;
@property NSDate *birthday;
@end

@implementation Person
+ (NSArray *)requiredProperties {
    return @[@"name"];
}
@end

存储可空数字目前已经可以通过 NSNumber * 属性完成。

由于 Realm 对不同类型的数字采取了不同的存储格式,因此设置可空的数字属性必须是 RLMInt、RLMFloat、RLMDouble 或者 RLMBool 类型。所有赋给属性的值都会被转换为其特定的类型。

请注意,NSDecimalNumber 的值只能分配给类型为 RLMDouble 的 Realm 属性,此外 Realm 将会存储近似于双精度浮点的数值,而不是存储基本的十进制数值。

比如说,如果我们存储一个用户的年龄(age)而不是存储他们的生日,同时还要允许当您不知道该用户的年龄的时候将 age 属性设置为 nil:

@interface Person : RLMObject
@property NSString *name;
@property NSNumber<RLMInt> *age;
@end

@implementation Person
+ (NSArray *)requiredProperties {
    return @[@"name"];
}
@end

RLMProperty 的子类属性始终都可以为 nil,因此这些类型不能够放在 requiredProperties中,并且 RLMArray 不支持存储 nil 值。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

5条评论
  • heweiming

    2017年4月16日 下午3:01

    自顶

  • Just want to say your article is as surprising. The clearness in your post is simply spectacular and i can assume you’re an expert on this subject.
    Well with your permission allow me to grab your RSS feed to keep updated with
    forthcoming post. Thanks a million and please continue the rewarding work.

  • Gpa Calculator Online Free

    2017年5月6日 上午5:45

    Hello would you mind letting me know which web host you’re utilizing?

    I’ve loaded your blog in 3 different web browsers and I must say this blog
    loads a lot quicker then most. Can you recommend
    a good web hosting provider at a reasonable price?
    Thanks a lot, I appreciate it!

    1. heweiming

      2017年5月11日 下午7:20

      The host is aliyun

  • cheap augmentin online

    2017年5月28日 上午1:26

    Hey there are using Wordpress for your site platform?

    I’m new to the blog world but I’m trying to get started and create my own.
    Do you require any coding knowledge to make your own blog?
    Any help would be greatly appreciated!

发表评论

电子邮件地址不会被公开。 必填项已用*标注