你还在用GUID作数据库表的主键吗?

数据库的物理设计, 对于要负载很多用户的大系统来说, 是有关系统生与死的关键问题之一. 好的设计可能比差的设计在性能上有数量级的差别. 这不仅仅是省掉花在昂贵的数据库服务器软硬件上的钱的问题,  还是关系的你的系统响应时间是否足够满足要求, 并最终影响到系统的用户接受度的问题.

由于data replication 的要求, 一段时间内, 把GUID作为数据库表的主键成为一种流行. 如果, 你现在还在用GUID, 那么, 下面的文章你一定要看看. 这是我在一个英文站上发的, 摘要的翻译了一下.

最近读到一篇文章说, fragmentation and page split 对性能很不好. 该文用了一个测试程序, 对使用guid作为clustered index的方案和使用identity 整数作为clustered index的方案进行了实际的性能比较. 结果是, guid 方案(会有fragmentation和page split)的速度仅仅有identity方案的速度的十分之一.

由于那个测试没有使用多线程, 而多线程是能否披露hotspot问题的关键, 所以我决定自己做一个测试(hotspot在使用identity 字段作为clustered index的方案中可能会成为性能的杀手). 我的测试用的机器是 2G 主频, 1G内存, ms sql 2005, 测试基础数据为一百万条记录, 一组测试使用guid方案, 另一组测试使用identity方案, 两组都使用5个线程, 并同时运行, 每个线程插入3000条记录, 这样一组总共新插入15000条新记录. 另外, 对guid方案还设置了fill factor 为90%, 以减少page split.  测试结果并没有象开始提到的那个结果那样的显著差别. identity方案仅比guid方案速度快一倍左右, 而不是十倍.

所以, 总的结果是, hotspot问题, 随着数据库技术的进步, 似乎已经不再是一个性能杀手了. (hotspot 主因是, 过去, 因为数据库engine 缺乏比较细粒度的锁(row level lock), 不同的线程在锁上等待)

Besides the disadvantage at fragmentation(not good if you are reading a continous range of records on a clustering key)  and page splitting for the GUID scheme, identity scheme also has advantage in terms of cache hit and data size. Since, if the GUID key is used, it's ussually chosen as the clustered key,  and since all other indexes use clustered key as row pointer, so the final increase in space occupation is even more bigger.

To reduce fragmentation and page splitting in the GUID scheme, one can use fill-factor. However, fill-factor can not totally elimminates fragmentation and page splitting. My observation is, even though I set a fill factor, I still get fragmentation. I observed, for initial fillfactor: 90% on 1 million existing row, after 15k new records inserted, a fairly big fragmentation rate for the GUID scheme than I would expect.

And don't foget that fill-factor also reduces read effeciency.


此外, GUID方案和identity方案, 当使用RAID存储时, 在性能上还有一个区别因素. GUID方案的读写磁头和区域是接近随机分配的, 而identity方案则是集中在一个区块的. The question remained is, if RAID is used,  will the identity scheme( the hotspot one) not fully use RAID's parallel IO ability?  Presumably, this will somehow be related to how stripe size compares with checkpoints pages number. If the checkpoint pages number(the number of dirty pages sql server commits to IO system in a batch) is big compared to stripe size, then IO will still be distributed across RAID disks.

To observe the checkpoint pages number, the  performance counter checkpoint pages/second is a close indicator.

In summary, Guids are good for presenting unique identifiers to outside appications and services. They are bad for performance.

Note, the above excludes other factors for performance, such as query pattern etc, in order to focus and simplify the discussion.

补:

尽管, 已经有两个测试都显示identity方案比GUID方案的性能显著的好, 但是, 测试目前仍然不是完全令人信服. 因为, 对于在实际中运行的系统来说, 一般都使用有多个cpu和RAID 存储的系统.  也就是说, 尽管使用了多线程来披露hotspot问题, 但是, 单个cpu的系统的多线程和多个cpu的多线程并不能完全相提并论. 另外, RAID的stripe size 与数据库的checkpoint page number的比例对性能的影响也是一个值得探讨的问题.

哪位如果能够提供多cpu的服务器做一个测试, 我这里有现成的script和程序, 我们可以一同把这个问题彻底搞清楚.

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭