本教程主要介绍WCDB-iOS/macOS中的对性能、错误的监控和处理。
阅读本教程前,建议先阅读iOS/macOS使用教程 和 基础类、CRUD与Transaction。
错误处理
WCDB可以对所有错误进行统一的监控,也可以获取某个特定操作的错误信息。所有错误都以WCTError
的形式出现。
WCTError
WCTError
继承自NSError
,包含了WCDB错误的所有信息,以供调试或发现问题。
type
表示错误的类型,不同类型的错误其错误码和拥有的信息不同。其对应关系如下
Type | Code |
---|---|
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,发生错误时正在操作的文件的路径。
获取错误
由于便捷接口的设计原则是易用,因此不提供获取错误的方式。错误处理需使用链式接口
- WCTSelect *select = [database prepareSelectObjectsOfClass:Message.class
- fromTable:@"message"];
- NSArray<Message *> *objects = [[[select where:Message.localID > 0]
- orderBy:Message.createTime.order()]
- limit:10].allObjects;
- WCTError *error = select.error;
开发者也可以注册全局的错误接口,以调试、上报、打log
- //Error Monitor
- [WCTStatistics SetGlobalErrorReport:^(WCTError *error) {
- NSLog(@"[WCDB]%@", error);
- }];
性能监控
WCDB支持获取单次操作的耗时,也支持对单个DB或全局注册统一接口监控性能。
所有性能监控都会有少量的性能损坏,请根据需求开启。
操作耗时
由于便捷接口的设计原则是易用,因此不提供获取错误的方式。操作耗时需使用链式接口。
首先安通过setStatisticsEnabled:
打开耗时监控
- WCTSelect *select = [database prepareSelectObjectsOfClass:Message.class
- fromTable:@"message"];
- [select setStatisticsEnabled:YES];//You should call this before all other operations.
在操作执行完成后,通过cost
接口获取耗时
- NSArray<Message *> *objects = [[[select where:Message.localID > 0]
- orderBy:Message.createTime.order()]
- limit:10].allObjects;
- NSLog(@"%f", select.cost);//You should call this after all other operations.
监控耗时
WCDB支持对所有SQL操作进行全局监控,也支持监控单个特定的数据库。
所有监控的返回数据都相同,包括三个数据:
- Tag,执行操作的数据库的tag
- sqls,执行的SQL和对应的次数。
- 对于非事务操作,则为单条SQL
- 对于事务操作,则为该次事务所执行的所有SQL和每个sql执行的次数
- cost,耗时
全局监控
监控所有db的数据库操作耗时,该接口需要在所有db打开、操作之前调用。
- [WCTStatistics SetGlobalTrace:^(WCTTag tag, NSDictionary<NSString *, NSNumber *> *sqls, NSInteger cost) {
- NSLog(@"Tag: %d", tag);
- [sqls enumerateKeysAndObjectsUsingBlock:^(NSString *sql, NSNumber *count, BOOL *) {
- NSLog(@"SQL: %@ Count: %d", sql, count.intValue);
- }];
- NSLog(@"Total cost %ld nanoseconds", (long) cost);
- }];
特定数据库监控
对于特定的数据库,该接口会覆盖全局监控的注册。
- [db setTrace:^(WCTTag tag, NSDictionary<NSString *, NSNumber *> *sqls, NSInteger cost) {
- NSLog(@"Tag: %d", tag);
- [sqls enumerateKeysAndObjectsUsingBlock:^(NSString *sql, NSNumber *count, BOOL *) {
- NSLog(@"SQL: %@ Count: %d", sql, count.intValue);
- }];
- NSLog(@"Total cost %ld nanoseconds", (long) cost);
- }];
操作耗时与监控耗时的不同
- 操作耗时的
cost
返回的耗时为浮点数的秒,监控耗时的cost
返回的耗时为整型的纳秒。 - 监控耗时仅包括SQL在SQLite层面的耗时,包括SQL的编译、I/O等。而操作耗时除以上之外,还包括了WCDB层面对类封装等产生的耗时
SQL执行监控
WCDB可以监控所有SQL的执行,以确定代码符合预期
- //SQL Execution Monitor
- [WCTStatistics SetGlobalSQLTrace:^(NSString *sql) {
- NSLog(@"SQL: %@", sql);
- }];