朱博的技术园

关注基于.Net的Web解决方案,高性能数据库设计,高性能Web服务解决方案

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  9 随笔 :: 0 文章 :: 144 评论 :: 2 引用
前言
我看过不少对Bit字段能否建立索引,以及建立索引后性能如何的讨论,还有朋友建议用Tinyint代替Bit,我在这里深入研究一下:

研究方法:
一、建立六张表,具体说明见SQL语句中的注释部分:
建表Sql语句

二、分别填充10万条数据,其中Bit与Tinyint各有一张表的0、1比例悬殊(97:3)
插入测试数据的Sql语句

三、分别搜索六张表中ColumnBit = 0 或者 ColumnTinyint = 0的数据,并在执行计划中查看I/0成本CPU成本成本
查询SQL语句

四、比较执行计划中的成本:


Test1:Bit无索引,0、1数据量相等


Test4:Tinyint无索引,0、1数据量相等


Test2:Bit有索引,0、1数据量相等


Test5:Tinyint有索引,0、1数据量相等


Test3:Bit有索引,0、1数据量悬殊


Test6:Tinyint有索引,0、1数据量悬殊


数据收集如下表:

 

I/O成本

CPU成本

成本

Bit无索引,01数据量相等

0.164

0.109

0.274653

Bit有索引,01数据量相等

0.110

0.109

0.220691

Bit有索引,01数据量悬殊

0.110

0.110

0.220990

Tinyint无索引,01数据量相等

0.164

0.109

0.274653

Tinyint有索引,01数据量相等

0.0426

0.0549

0.097554

Tinyint有索引,01数据量悬殊

0.0774

0.106

0.184218


数据分析:
1、对于Bit,有索引与无索引、01数据量相等与数据量悬殊的各项成本相差都不大;
2、对于Tinyint,01数据量相等时,有索引比无索引降低I/O成本接近5倍、降低CPU成本近2倍、降低成本近3倍;
3、对于Tinyint,01数据量悬殊时,比数据量相等要增加各项成本近2倍;
4、无索引、数据量相同时,Bit与Tinyint成本完全相同;
5、有索引、数据量相同时,Bit比Tinyint增加成本接近3倍;
6、有索引、数据量悬殊时,Bit比Tinyint增加成本近2倍。

结论:
1、毋庸置疑,Bit可以建立索引;
2、在10万条数据时,Bit是否建立索引成本消耗相差不大;
3、强烈推荐用Tinyint代替Bit,10万条数据时,成本降低近3倍,相信随着数据量的增加,与Bit相比成本降低会更多,有兴趣的朋友可以再深入测试一下。

参考:
http://sqlserver2000.databases.aspfaq.com/can-i-create-an-index-on-a-bit-column.html
posted on 2008-02-27 01:03 朱博 阅读(2181) 评论(24)  编辑 收藏 网摘

评论

#1楼  2008-02-27 04:21 梁逸晨      
我的疑问是:既然如此,Bit的存在价值何在?
  回复  引用  查看    

#2楼  2008-02-27 08:34 大石头      
Bit可以节省空间吧
  回复  引用  查看    

#3楼 [楼主] 2008-02-27 09:23 朱博      
@大石头
貌似不是这样:
bit:如果一个表中有不多于 8 个的 bit 列,这些列将作为一个字节存储。如果表中有 9 到 16 个 bit 列,这些列将作为两个字节存储。更多列的情况依此类推。
tinyint:从 0 到 255 的整型数据。存储大小为 1 字节。

资料来源:SQL Server 联机丛书
  回复  引用  查看    

#4楼  2008-02-27 09:41 Dove.Net      
--引用--------------------------------------------------
梁逸晨: 我的疑问是:既然如此,Bit的存在价值何在?
--------------------------------------------------------
同问
  回复  引用  查看    

#5楼 [楼主] 2008-02-27 09:48 朱博      
@Dove.Net
@梁逸晨
我也存在这个疑问,希望知道的朋友能分享一下
  回复  引用  查看    

#6楼  2008-02-27 09:54 马可香蕉      
LZ工作做得很细啊
  回复  引用  查看    

#7楼  2008-02-27 10:06 老Q      
主要现在硬件价格白菜了。
所以大家都不关心空间的占用。
  回复  引用  查看    

#8楼  2008-02-27 10:16 Cheney Shue      
你这个是预计的执行计划还是实际的执行计划?
  回复  引用  查看    

#9楼 [楼主] 2008-02-27 10:26 朱博      
@Cheney Shue
实际的

  回复  引用  查看    

#10楼  2008-02-27 10:27 Cat Chen      
bit根本不省空间,只是严谨一些。现在已经不会说有8个bit就挤在一起占一个byte的事情了,无论是硬盘里还是内存里,这种数据结构都直接占一个byte甚至一个word。
  回复  引用  查看    

#11楼  2008-02-27 10:52 Cheney Shue      
I/O成本似乎有问题,不知是怎么统计的,如今输出TestID,I/O其实是一样的,如果包括了Scan输出量,Byte应该比TinyInt小才对
  回复  引用  查看    

#12楼  2008-02-27 11:11 xingd      
bit会压缩存储的,不过我也同意楼主的结论,如果需要建立索引,可以考虑用tinyint来代替bit。

实际情况要复杂得多,像例子中的表,不建索引,直接table scan也未必慢多少。如果select返回的列比较多,在bit上建索引就更不值得了。
  回复  引用  查看    

#13楼  2008-02-27 15:17 ludao [未注册用户]
现在 内存 硬盘 设备 那么便宜

提倡 空间 换 速度哦...
  回复  引用    

#14楼  2008-02-27 17:43 WAV [未注册用户]
好文。bit并不好用,还得转换。看来还是tinyint吧。
  回复  引用    

#15楼  2008-02-27 18:20 JoeLee [未注册用户]
粗略看了下.说几个问题.
1.BIT在SQLSERVER中.即使只有1位,那么也要占1个字节.也就是8位的.
当然多个BIT会共享这个1个字节.从索引页的角度考虑.这是不明智的做法.索引占用了索引8倍的空间,IO操作必然增加.
2.建立索引的原则是高选择性,低密度.BIT只有两种状态.何来高选择性,低密度?
3.BIT是SQL SERVER特有的数据类型.尽量少用.否则跨数据库时会出麻烦.甚至TINYINT也少用.
觉得不是为了特别的要求.对这种东西建立索引没啥必要.

具体内容请参见SQL SERVER MCP教材.蓝本的厚厚的那个.

  回复  引用    

#16楼 [楼主] 2008-02-27 18:33 朱博      
@JoeLee
理论上讲,建立索引的原则是高选择性,低密度,但是从实验得出的数据来看,并不是这样,尤其是tinyint建立索引后对成本的消耗降低了近3倍,而这里仅仅只有10万条数据。

我没有在更大的数据量上做过测试,希望有兴趣的朋友可以试一下,验证一下我的结论是否成立。

谢谢参与讨论。
  回复  引用  查看    

#17楼 [楼主] 2008-02-27 18:34 朱博      
@Cheney Shue
我没办法从理论上来分析这个事实成立的原因,从实验结果看,我的结论是成立的,也希望感兴趣的朋友能按照我的实验步骤来一次测试,可以数据量选择地更大一点。

感谢参与讨论。
  回复  引用  查看    

一般我就直接用 int 了。省事,以后怎么扩充都可以,当然会比较浪费硬盘空间。

至于索引嘛,个人感觉bit只有两种状态,建立索引也没有太大的意思,理论上讲可以减少一般的资源吧。

另外 你做测试的时候好像都是 ColumnTinyint = 0 。

那么在相差悬殊的时候 是 0 多还是 1 多呢? 如果 ColumnTinyint = 1 ,结果会不会不一样呢?


Bit有索引,0、1数据量相等
0.110
0.109
0.220691

Bit有索引,0、1数据量悬殊
0.110
0.110
0.220990


这两个基本一致,说明数量的比例没有什么影响,但看这一块的话,我感觉索引根本就没有起作用。

但是看第一行,比没有索引的数据又能快一点,不好理解了。


如果真的是 多个 bit会挤在一个字节里的话,那么这时索引会起作用吗?


另外还项建议一下,一个表里面有多个bit的时候的效率。

不好意思,最近比较烦,我就不测试了,仅提几个建议。



  回复  引用  查看    

#19楼  2008-02-28 10:09 egmkang      
bit本身就是tinyint.
只不过几个bit有可能存储在一个位置,而tinyint肯定是分开存储的,所以tinyint的索引效率比较高.
  回复  引用  查看    

如果这样的话,Bit的价值就不大了!
  回复  引用    

#21楼  2008-02-28 12:56 114411 [未注册用户]
我觉得你那个 where 条件 等于0 和等于1都要测试才行,两者数量相差大时,查询性能会差很多,另外,你那个 TestID 是主键吧,你得找个不是主键的,没索引的字段来试一下才会比较准确一些吧
虽然我没详细测过,但是推测当select 语句中非索引非主键字段比较多时,当bit 或 tinyint值为0为1不可测时,加索引在性能上应该不会有太明显提高
不过tinyint相对于bit的性能倒有可能会高一些
  回复  引用    

粗略的看了一下,发现测试数据有问题,下面的结论就没看了。


  回复  引用    

IF @i > 50000
SET @SameBitFlag = 1
SET @SameTinyintFlag = 1

IF @i > 97000
SET @WideGapBitFlag = 1
SET @WideGapTinyintFlag = 1

---

这样实际上插入的99999笔@SameTinyintFlag=1及@WideGapTinyintFlag=1的记录..


  回复  引用    

#24楼 [楼主] 2008-11-09 19:01 朱博      
@Garnett_KG
谢谢你的回应,但我没有明白你的意思,因为@SameTinyintFlag与@WideGapTinyintFlag的初始值是0,当@i > 50000 与@i > 97000 时进行@SameTinyintFlag=1及@WideGapTinyintFlag=1赋值,就是为了增加01数量相当与01数量悬殊的样本数据。

麻烦指正。
  回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
Google站内搜索

相关文章:


相关搜索:
sqlserver 索引 bit tinyint

相关链接: