我想切换到 OrmLite,我需要弄清楚它是否很慢,如果是,原因是什么。
在我的研究中,我得出的结论是,复杂的对象(在 OrmLite 中被 blob 为 JSON)是 SELECT 速度非常慢的罪魁祸首。
因此,我创建了一个仅关注 OrmLite 的新项目,不与除自身之外的任何其他项目进行比较,这里的目的是了解具有 blob 的 JSON 对象与不具有它们之间的差异。
可以在 GitHub 上找到:https://github.com/tedekeroth/ormlitebenchmarking https://github.com/tedekeroth/ormlitebenchmarking
解决方案如下所示:
我正在 Windows 7、2.6Ghz、24 GB RAM 上运行 OrmLite 5.1.1,当前没有 CPU 负载,使用 MySql 5.6。应用程序连接到 127.0.0.1(root/root)并需要数据库“ormlite”。
我已启用 ThrowOnError:
OrmLiteConfig.ThrowOnError = JsConfig.ThrowOnError = true;
该应用程序如下所示:
没有数据:只有创建的对象,没有属性有数据:
基元:仅填充一些简单的基元属性:
Prim + 一个复杂对象:上述所有基元 + 一个 blobed 复杂对象:
完整数据:以上所有内容 + 另外 2 个复杂的 blob 对象:
The Create按钮首先在列表中创建 10 000 个对象,然后使用 OrmLite Insert 方法将它们持久化。时间测量仅针对 INSERT,而不是创建对象。
public void AddRow<T>(T coreObject) where T : CoreObject
{
long id = 0;
using (var _db = _dbFactory.Open())
{
id = _db.Insert<T>(coreObject, selectIdentity: true);
}
}
The Read按钮读取表中的所有行,并重新创建 Customer 对象:
public List<T> FetchAll<T>()
{
using (var _db = _dbFactory.Open())
{
List<T> list = _db.Select<T>();
return list;
}
}
因此,测试应该像这样进行:
- 选择模式,然后按Create, 将显示花费的时间
- Press Read读回表中当前的所有行
要测试另一种模式,请清空数据库表(customer
)有一个干净的。
基准测试
INSERT
创建 10 000 个对象(未测量)并将它们插入数据库。
- No data: ~26-27 seconds
- Primitives: ~27.1-27.4 seconds
- Prim + one complex: ~27.5-29 seconds
- Full data: ~28 seconds
所以,总而言之,大约相同,26-29 秒。
SELECT
从数据库读取 10 000 个对象,如上面插入的。
- No data: ~460 ms
- Primitives: ~700-720 ms
- Prim + one complex: ~970-1030 ms
- Full data: 30000-32000 ms (30-32 seconds)
结论
“完整数据”显然是最大的打击出现的地方。
添加的复杂 blob 对象 (ContactDetails
),似乎把事情搞砸了。我在之前的测试中注意到了这一点,但该对象本身并不是很复杂,请参见下文。所以,我不确定为什么会这样跳,或者这些数字是否合理。
我之前曾就此问题提出过问题,但这个基准测试应该更准确。
问题是:为什么持久化对象(按照 OrmLite 保存为 JSON)会以这种方式减慢 SELECT 速度?
[Serializable]
public class ContactDetails
{
public List<ContactItem> ContactItemList
{
get; set;
}
public ContactItem CurrentContactItem
{
get; set;
}
public ContactItem DefaultContactItem
{
get; set;
}
public bool IgnorePrimaryWaitBuffer
{
get; set;
}
public ContactDetails(List<ContactItem> contactItemList, ContactItem currentContactItem, ContactItem defaultContactItem)
{
ContactItemList = contactItemList;
CurrentContactItem = currentContactItem;
DefaultContactItem = defaultContactItem;
}
public ContactDetails()
{
}
}