本教程主要介绍WCDB-iOS/macOS中的对性能、错误的监控和处理。

阅读本教程前,建议先阅读iOS/macOS使用教程基础类、CRUD与Transaction

错误处理

WCDB可以对所有错误进行统一的监控,也可以获取某个特定操作的错误信息。所有错误都以WCTError的形式出现。

WCTError

WCTError继承自NSError,包含了WCDB错误的所有信息,以供调试或发现问题。

type表示错误的类型,不同类型的错误其错误码和拥有的信息不同。其对应关系如下

TypeCode
SQLite,表示该错误来自SQLite接口请参考rescode
SystemCall,表示该错误来自系统调用请参考errno
Core,表示该错误来自WCDB Core层请参考源码的error.hpp
Interface,表示该错误来自WCDB Interface层请参考源码的error.hpp
Abort,表示中断,该错误一般是开发错误,应该在发布前修复/
Warning,表示警告,建议修复/
SQLiteGlobal,表示该信息来自SQLite的log接口,一般只作为debug log请参考rescode

其他错误信息通过infoForKey接口获得,包括:

  • Tag,正在操作的数据库的tag
  • Operation,正在进行的操作,请参考error.hpp
  • Extended Code,SQLite的扩展码,请参考rescode
  • Message,错误信息
  • SQL,发生错误时正在执行的SQL
  • Path,发生错误时正在操作的文件的路径。

获取错误

由于便捷接口的设计原则是易用,因此不提供获取错误的方式。错误处理需使用链式接口

  1. WCTSelect *select = [database prepareSelectObjectsOfClass:Message.class
  2. fromTable:@"message"];
  3. NSArray<Message *> *objects = [[[select where:Message.localID > 0]
  4. orderBy:Message.createTime.order()]
  5. limit:10].allObjects;
  6. WCTError *error = select.error;

开发者也可以注册全局的错误接口,以调试、上报、打log

  1. //Error Monitor
  2. [WCTStatistics SetGlobalErrorReport:^(WCTError *error) {
  3. NSLog(@"[WCDB]%@", error);
  4. }];

性能监控

WCDB支持获取单次操作的耗时,也支持对单个DB或全局注册统一接口监控性能。

所有性能监控都会有少量的性能损坏,请根据需求开启。

操作耗时

由于便捷接口的设计原则是易用,因此不提供获取错误的方式。操作耗时需使用链式接口。

首先安通过setStatisticsEnabled:打开耗时监控

  1. WCTSelect *select = [database prepareSelectObjectsOfClass:Message.class
  2. fromTable:@"message"];
  3. [select setStatisticsEnabled:YES];//You should call this before all other operations.

在操作执行完成后,通过cost接口获取耗时

  1. NSArray<Message *> *objects = [[[select where:Message.localID > 0]
  2. orderBy:Message.createTime.order()]
  3. limit:10].allObjects;
  4. NSLog(@"%f", select.cost);//You should call this after all other operations.

监控耗时

WCDB支持对所有SQL操作进行全局监控,也支持监控单个特定的数据库。

所有监控的返回数据都相同,包括三个数据:

  • Tag,执行操作的数据库的tag
  • sqls,执行的SQL和对应的次数。
    • 对于非事务操作,则为单条SQL
    • 对于事务操作,则为该次事务所执行的所有SQL和每个sql执行的次数
  • cost,耗时

全局监控

监控所有db的数据库操作耗时,该接口需要在所有db打开、操作之前调用。

  1. [WCTStatistics SetGlobalTrace:^(WCTTag tag, NSDictionary<NSString *, NSNumber *> *sqls, NSInteger cost) {
  2. NSLog(@"Tag: %d", tag);
  3. [sqls enumerateKeysAndObjectsUsingBlock:^(NSString *sql, NSNumber *count, BOOL *) {
  4. NSLog(@"SQL: %@ Count: %d", sql, count.intValue);
  5. }];
  6. NSLog(@"Total cost %ld nanoseconds", (long) cost);
  7. }];

特定数据库监控

对于特定的数据库,该接口会覆盖全局监控的注册。

  1. [db setTrace:^(WCTTag tag, NSDictionary<NSString *, NSNumber *> *sqls, NSInteger cost) {
  2. NSLog(@"Tag: %d", tag);
  3. [sqls enumerateKeysAndObjectsUsingBlock:^(NSString *sql, NSNumber *count, BOOL *) {
  4. NSLog(@"SQL: %@ Count: %d", sql, count.intValue);
  5. }];
  6. NSLog(@"Total cost %ld nanoseconds", (long) cost);
  7. }];

操作耗时与监控耗时的不同

  • 操作耗时的cost返回的耗时为浮点数的秒,监控耗时的cost返回的耗时为整型的纳秒。
  • 监控耗时仅包括SQL在SQLite层面的耗时,包括SQL的编译、I/O等。而操作耗时除以上之外,还包括了WCDB层面对类封装等产生的耗时

SQL执行监控

WCDB可以监控所有SQL的执行,以确定代码符合预期

  1. //SQL Execution Monitor
  2. [WCTStatistics SetGlobalSQLTrace:^(NSString *sql) {
  3. NSLog(@"SQL: %@", sql);
  4. }];