随笔-104  评论-1067  文章-1  trackbacks-1

极限挑战—C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码)

    实际工作中有时候需要把大量数据导入数据库,然后用于各种程序计算,本实验将使用5中方法完成这个过程,并详细记录各种方法所耗费的时间。

    本实验中所用到工具为VS2008和SQL SERVER 2000、SQL SERVER 2008,分别使用5中方法将100万条数据导入SQL 2000与SQL 2008中,实验环境是DELL 2850双2.0GCPU,2G内存的服务器。感兴趣的朋友可以下载源代码自己验证一下所用时间。

    还要有一点需要进行说明,本实验中执行SQL语句的地方使用了IsLine FrameWork框架中的DataProvider模块,这个模块只是对SQL配置的读取和封装,并不会对最终结果有本质性的影响,关于IsLine FrameWork框架方面的知识,请参考“IsLine FrameWork”框架系列文章。

    下面进入正题,分别使用基本的Insert 语句、使用BULK INSERT语句、在多线程中使用BULK INSERT、使用SqlBulkCopy类、在多线程中使用SqlBulkCopy类五种方法,挑战4秒极限。

    数据库方面使用SQL 2000与SQL 2008,表名TableB,字段名称为Value1,数据库名可以在App.config中修改,默认为test。

 

图 1 试验中的5种方法

 

    方法一.使用基本的Insert 语句

    这种方法是最基本的方法,大多数人一开始都会想到这种方法。但是Insert语句似乎并不适合大批量的操作,是不是这样呢?

    本方法中将100万数据分为10个批次,每个批次10万条,每10万条1个事务,分10次导入数据库。

    基本语句:Insert Into TableB (Value1) values (‘”+i+”’);

    说明:语句中的i是宿主程序中的一个累加变量,用于填充数据库字段中的值。

    SQL 2000 耗时:901599

    SQL 2008耗时:497638

    方法二.使用BULK INSERT语句

    这个类的效果,在本实验中可以说是最令人满意的了,它的使用最简便、灵活,速度很快。

    “BULK INSERT”语句似乎不是很常用, Aicken听说Oracle中有一种可以将外部文件映射为Oracle临时表,然后直接将临时表中的数据导入Oracle其他表中的方法,这种方法的速度非常令人满意,SQL SERVER的BULK INSERT是不是同样令人满意呢?

    基本语句:BULK INSERT TableB FROM 'c:\\sql.txt' WITH (FIELDTERMINATOR = ',',ROWTER /.,mbMINATOR='|',BATCHSIZE = 100000)

    说明:“c:\\sql.txt”是一个预先生成的包含100条数据的文件,这些数据以“|”符号分隔,每10万条数据一个事务。

    SQL 2000耗时:4009

    SQL 2008耗时:10722

    方法三.在多线程中使用BULK INSERT

    在方法二的基础上,将100万条数据分五个线程,每个线程负责20万条数据,每5万条一个事物,五个线程同时启动,看看这样的效果吧。

    SQL 2000耗时:21099

    SQL 2008耗时:10997

    方法四.使用SqlBulkCopy类

    这种方法速度也很快,但是要依赖内存,对于几千万条、多字段的复杂数据,可能在内存方面会有较大的消耗,不过可以使用64位解决方案处理这个问题。

    几千万条、多字段的数据的情况一般在一些业务场景中会遇到,比如计算全球消费者某个业务周期消费额时,要先获得主数据库表中的会员消费记录快照,并将快照储存至临时表中,然后供计算程序使用这些数据。并且有些时候消费者的消费数据并不在一台数据库服务器中,而是来自多个国家的多台服务器,这样我们就必须借助内存或外存设备中转这些数据,然后清洗、合并、检测,最后导入专用表供计算程序使用。

    基本语句:

代码
using (System.Data.SqlClient.SqlBulkCopy sqlBC = new System.Data.SqlClient.SqlBulkCopy(conn))

{

sqlBC.BatchSize
= 100000;

sqlBC.BulkCopyTimeout
= 60;

sqlBC.DestinationTableName
= "dbo.TableB";

sqlBC.ColumnMappings.Add(
"valueA", "Value1");

sqlBC.WriteToServer(dt);

}

说明:

       BatchSize = 100000; 指示每10万条一个事务并提交

       BulkCopyTimeout = 60; 指示60秒按超时处理

       DestinationTableName = "dbo.TableB"; 指示将数据导入TableB表

       ColumnMappings.Add("valueA", "Value1"); 指示将内存中valueA字段与TableB中的Value1字段匹配

       WriteToServer(dt);写入数据库。其中dt是预先构建好的DataTable,其中包含valueA字段。

SQL 2000耗时:4989

SQL 2008耗时:10412

    方法五.在多线程中使用SqlBulkCopy类

    基于方法四,将100万条数据分五个线程,每个线程负责20万条数据,每5万条一个事物,五个线程同时启动,看看这样的效果吧。

    SQL 2000耗时:7682

    SQL 2008耗时:10870

总结

           数据库

测试方式

SQL 2000

SQL 2008

基本Insert Into

901599

497638

单线程Bulk Insert

4209

10722

多线程Bulk Insert

21099

10997

单线程SqlBulkCopy

4989

10412

多线程SqlBulkCopy

7682

10870

    以上就是这几天的实验结果了,比较令人失望的是SQL SERVER 2008导入数据的性能似乎并不想我们想象的那样优秀。

    另外,有下载源代码的帮我看看,为什么多线程的成绩还不如单线程的优秀呢?是静态资源使用不当造成的,还是其他什么原因?

    源码地址:http://files.cnblogs.com/isline/sqltest.rar

    测试数据下载地址:http://files.cnblogs.com/isline/Data.rar

    我是李鸣(Aicken) 欢迎您关注我的下一篇文章。

天道酬勤不酬怨
李鸣(aicken)原创 转载注明
posted on 2010-03-18 11:13 Aicken(李鸣) 阅读(17058) 评论(80) 编辑 收藏

评论:
#1楼 2010-03-18 11:26 | riccc      
虽然用的多线程,瓶颈应该在数据库上,insert操作可能锁住了索引、表,没法并行
 回复 引用 查看   
#2楼 2010-03-18 11:26 | Allen Zhang      
这方面SQL 2008对比SQL 2000好像并没有优势嘛。
 回复 引用 查看   
#3楼 2010-03-18 11:33 | Cheney Shue      
在多线程下,你可以给表建多个分区,然后每个线程向一个分区写数据。或者是降低锁的级别。

2008比2000慢,你可以认为,新版本比老版本更完善了。例如,mysql中myisam比innodb快,但并不适合并发操作,innodb为了实现数据的一致性,要产生log、undo等操作,所以比较慢。

 回复 引用 查看   
#4楼[楼主] 2010-03-18 11:34 | 李鸣(aicken)      
引用riccc:虽然用的多线程,瓶颈应该在数据库上,insert操作可能锁住了索引、表,没法并行


其实这次同时进行了2个实验,一个使用SQL一个使用Oracle。Oracle 10g的最佳成绩是2秒。这一点SQL SERVER还有进步的空间。

 回复 引用 查看   
#5楼[楼主] 2010-03-18 11:34 | 李鸣(aicken)      
引用Allen Zhang:这方面SQL 2008对比SQL 2000好像并没有优势嘛。


失望

 回复 引用 查看   
#6楼 2010-03-18 11:36 | aspnetx      
AK47,帅
 回复 引用 查看   
#7楼[楼主] 2010-03-18 11:36 | 李鸣(aicken)      
引用Cheney Shue:
在多线程下,你可以给表建多个分区,然后每个线程向一个分区写数据。或者是降低锁的级别。

2008比2000慢,你可以认为,新版本比老版本更完善了。例如,mysql中myisam比innodb快,但并不适合并发操作,innodb为了实现数据的一致性,要产生log、undo等操作,所以比较慢。


嗯。。。

 回复 引用 查看   
#8楼 2010-03-18 11:36 | Cheney Shue      
引用李鸣(aicken):
引用riccc:虽然用的多线程,瓶颈应该在数据库上,insert操作可能锁住了索引、表,没法并行


其实这次同时进行了2个实验,一个使用SQL一个使用Oracle。Oracle 10g的最佳成绩是2秒。这一点SQL SERVER还有进步的空间。



Oracle中用direct insert,性能会成倍增加,insert后要checkpoint才算真正的写入到磁盘。

 回复 引用 查看   
#9楼 2010-03-18 11:53 | 马千里的博客      
游戏而已,实际情况下就算需要导入大批量数据,也不在乎那么几秒。
 回复 引用 查看   
#10楼 2010-03-18 12:13 | Anders Liu      
有句古话说得好:凡是I/O密集的操作都不要用多线程。
 回复 引用 查看   
#11楼 2010-03-18 12:26 | 萧寒      
我想知道生成 'c:\\sql.txt' 这个100万条数据的文件几秒?
 回复 引用 查看   
#12楼 2010-03-18 12:34 | zeus2      
楼主试试使用事务进行插入。
 回复 引用 查看   
#13楼[楼主] 2010-03-18 12:35 | 李鸣(aicken)      
引用马千里的博客:游戏而已,实际情况下就算需要导入大批量数据,也不在乎那么几秒。


玩呗。。。

 回复 引用 查看   
#14楼[楼主] 2010-03-18 12:36 | 李鸣(aicken)      
引用Anders Liu:有句古话说得好:凡是I/O密集的操作都不要用多线程。


应该不是IO的瓶颈

 回复 引用 查看   
#15楼[楼主] 2010-03-18 12:36 | 李鸣(aicken)      
引用萧寒:我想知道生成 'c:\\sql.txt' 这个100万条数据的文件几秒?


生成数据文件的时间不包含在实验当中

 回复 引用 查看   
#16楼[楼主] 2010-03-18 12:37 | 李鸣(aicken)      
引用zeus2:楼主试试使用事务进行插入。


每5-10万条数据一个事务

 回复 引用 查看   
#17楼 2010-03-18 12:46 | dege301      
非DBA的飘过,我更注重业务。
 回复 引用 查看   
#18楼 2010-03-18 13:09 | chingho      
有好几种方法,都没用过,mark。
回去研究研究。

 回复 引用 查看   
#19楼[楼主] 2010-03-18 13:10 | 李鸣(aicken)      
引用dege301:非DBA的飘过,我更注重业务。

高科技。。。

 回复 引用 查看   
#20楼[楼主] 2010-03-18 13:10 | 李鸣(aicken)      
引用chingho:
有好几种方法,都没用过,mark。
回去研究研究。


欢迎交流

 回复 引用 查看   
#21楼 2010-03-18 13:56 | n216      
楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!
 回复 引用 查看   
#22楼 2010-03-18 13:59 | 晴朗天空      
可以看出,2008在用的最频繁的insert操作上进步明显,节省了4成的时间。但是在大批量工作中,反而退步了……
上面的一位TX说的对,应该是安全性等方面的提高,使2008消耗了大量时间。以前从2000升级到2005也有类似问题,2005对数据的核查、备份比以前多做了很多工作,虽然很多时候,这些安全性并不是我们要的,往往单纯的速度才是关键。

 回复 引用 查看   
#23楼[楼主] 2010-03-18 14:01 | 李鸣(aicken)      
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。

 回复 引用 查看   
#24楼[楼主] 2010-03-18 14:02 | 李鸣(aicken)      
引用晴朗天空:
可以看出,2008在用的最频繁的insert操作上进步明显,节省了4成的时间。但是在大批量工作中,反而退步了……
上面的一位TX说的对,应该是安全性等方面的提高,使2008消耗了大量时间。以前从2000升级到2005也有类似问题,2005对数据的核查、备份比以前多做了很多工作,虽然很多时候,这些安全性并不是我们要的,往往单纯的速度才是关键。



是的,2005与2008在所耗时间上相似,这里只列出了2000和2008的测试结果。

 回复 引用 查看   
#25楼 2010-03-18 14:07 | n216      
引用李鸣(aicken):
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。

想说就说,不要不好意思!

 回复 引用 查看   
#26楼 2010-03-18 14:09 | 常言不哭      
写的不错的,支持一下。
 回复 引用 查看   
#27楼[楼主] 2010-03-18 14:17 | 李鸣(aicken)      
引用n216:
引用李鸣(aicken):
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。

想说就说,不要不好意思!


这位同学,你不会分不清100万和1000的区别吧。。。
再有,这个实验能度量的是记录数量,记录大小是没有度量标准的,不然你说使用多大的记录来试验合适?
我只能节省一切可以节省的资源,返回一个最好的成绩!

 回复 引用 查看   
#28楼[楼主] 2010-03-18 14:17 | 李鸣(aicken)      
引用常言不哭:写的不错的,支持一下。


嗯 多谢支持!

 回复 引用 查看   
#29楼 2010-03-18 14:18 | ERic Poon      
博主分析得很好。可是不知道测试这个时间对实际开发环境有多大的帮助。
另外,2005、2008使用整合服务进行导入已经很方便,至少比2000下使用DTS来得方便和完美。


 回复 引用 查看   
#30楼[楼主] 2010-03-18 14:32 | 李鸣(aicken)      
引用ERic Poon:
博主分析得很好。可是不知道测试这个时间对实际开发环境有多大的帮助。
另外,2005、2008使用整合服务进行导入已经很方便,至少比2000下使用DTS来得方便和完美。


没错,说到DTS才是2005与2008进步的根本。
不过实验一是兴趣所在,二是为了更好的了解各种技术,毕竟有些时候我们是在不同数据源之间进行数据传递。

 回复 引用 查看   
#31楼 2010-03-18 14:38 | Jertun      
引用李鸣(aicken):
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。


我是小学生,lz请教一下,上面那位是怎么算的?费解....

 回复 引用 查看   
#32楼 2010-03-18 14:43 | n216      
引用李鸣(aicken):
引用n216:
引用李鸣(aicken):
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。

想说就说,不要不好意思!


这位同学,你不会分不清100万和1000的区别吧。。。
再有,这个实验能度量的是记录数量,记录大小是没有度量标准的,不然你说使用多大的记录来试验合适?
我只能节省一切可以节省的资源,返回一个最好的成绩!

不好意思1000条记录应该写成100万记录的。是我打错了。
一个字段算4个字节,100万条=4*100*10000字节=4M
我说的应该没有变化的。
你说的实验的目的是什么,就决定你的样本是什么,如果要测试大数据量数据或海量数据,100万条是不够的,100万条还不是大数据量的一个起点,大数据量起点一般要在千万级以上,而且数据库容量要在G级(字段字节总数*记录数。且不考虑索引等开销)。
如果要测试数据库的命令的解释时间,一般不采用插入语句,而是采用select语句,更有意义。
要测试insert一般会考虑批处理方式和单笔处理方式对效率的影响。本质是insert的解释时间的影响。

 回复 引用 查看   
#33楼[楼主] 2010-03-18 15:14 | 李鸣(aicken)      
引用n216:
引用李鸣(aicken):
引用n216:
引用李鸣(aicken):
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。

想说就说,不要不好意思!


这位同学,你不会分不清100万和1000的区别吧。。。
再有,这个实验能度量的是记录数量,记录大小是没有度量标准的,不然你说使用多大的记录来试验合适?...


1.“一个字段算4个字节,100万条=4*100*10000字节=4M”----为何算4字节?
2.“你说的实验的目的是什么,就决定你的样本是什么,如果要测试大数据量数据或海量数据,100万条是不够的,100万条还不是大数据量的一个起点,大数据量起点一般要在千万级以上,而且数据库容量要在G级(字段字节总数*记录数。且不考虑索引等开销)。”----我读不出你想说什么。。。我只是向大家说明了100万条数据的导入SQL的极限最好成绩,仅此而已。你那些什么G级数据库,千万条数据,如果真的这么做了,无非是改个题目:“1000万数据导入数据库40秒”,事实上千万条数据的实验也做了,可是这有什么意义呢?数据量变了,时间也会变,100万条不多也不少,很能说明问题。
况且即使我发布了1千万条数据的测试结果,还会有人跳出来说,你应该测试1亿的数据--这完全是口水仗!
再说一遍,实验的目的是考察一定量数据的最佳时间,100万换成1000万只是时间不同了,说明的问题都一样!
 回复 引用 查看   
#34楼[楼主] 2010-03-18 15:17 | 李鸣(aicken)      
引用Jertun:
引用李鸣(aicken):
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。


我是小学生,lz请教一下,上面那位是怎么算的?费解....

呵呵,他可能看错了。。。

 回复 引用 查看   
#35楼 2010-03-18 15:51 | blackcat      
引用李鸣(aicken):
引用n216:
引用李鸣(aicken):
引用n216:
引用李鸣(aicken):
引用n216:楼主还是个小学生!1000条记录实际大小4M大小,要入数据库化4秒。还算快吗?考虑数据插入操作,不但要考虑记录条数,而且要考虑记录大小,插入操作主要时间消耗在I/o上。这些基本道理楼主懂了以后,就不会这样写了!


不知说你什么好。。。

想说就说,不要不好意思!


这位同学,你不会分不清100万和1000的区别吧。。。
再有,这个实验能度量的是记录数量,记录大小是没有度量标准...


其实我是支持这位兄弟的。在这个方面楼主确实是“小学生”。
我的入库程序,都是单线程的批量入库。
服务器端需要做一定优化,尤其是oracle,不要让log file sync占用了主要时间,表结构决定了更多,比如物理存储结构,比如索引结构数量,等等,等等。
还有,就是持续的时间,比如有些方法,感觉很快,但是不具有可持续性,你会发现越来越慢,越来越慢。

了解了数据库的工作方式,我想,这些都不是问题。
 回复 引用 查看   
#36楼 2010-03-18 15:51 | n216      
1.“一个字段算4个字节,100万条=4*100*10000字节=4M”----为何算4字节?
2.“你说的实验的目的是什么,就决定你的样本是什么,如果要测试大数据量数据或海量数据,100万条是不够的,100万条还不是大数据量的一个起点,大数据量起点一般要在千万级以上,而且数据库容量要在G级(字段字节总数*记录数。且不考虑索引等开销)。”----我读不出你想说什么。。。我只是向大家说明了100万条数据的导入SQL的极限最好成绩,仅此而已。你那些什么G级数据库,千万条数据,如果真的这么做了,无非是改个题目:“1000万数据导入数据库40秒”,事实上千万条数据的实验也做了,可是这有什么意义呢?数据量变了,时间也会变,100万条不多也不少,很能说明问题。
况且即使我发布了1千万条数据的测试结果,还会有人跳出来说,你应该测试1亿的数据--这完全是口水仗!
再说一遍,实验的目的是考察一定量数据的最佳时间,100万换成1000万只是时间不同了,说明的问题都一样!
---------------------
第一个问题,我看到你插入的i,是一个整型,而一个整型一般是4个字节。
第二个问题,数据库效率并非是简单的线性关系,不同的数据库对算法和效率影响是不一样的。而记录条数也是有等级之分的。
到了超大记录(亿条T级),在大记录有效的算法可能也需要改变的。效率问题远远比我们看到和想到的复杂。关键一点,是要有这方面的积累和经验,只有做过这方面的工作,可能才能对效率有一个很客观的理解。泛泛谈什么极限是没有什么意义的,这可能对初学者有一个好奇和误导的影响。
我想到不如更多地建议新手多看看数据库基础理论方面的书,找找影响效率的几个方面,在实践中去感觉效率的影响。

 回复 引用 查看   
#37楼 2010-03-18 15:54 | blackcat      
补充一点,如果想测试极限速度,可以直接用sql select into 方式,试试新生成的速度。然后对比外部程序。这样你可以知道你的数据在准备,传输,入库等各个地方的消耗。
 回复 引用 查看   
#38楼 2010-03-18 15:55 | blackcat      
n216,加个好友吧。我加你了。
 回复 引用 查看   
#39楼[楼主] 2010-03-18 16:17 | 李鸣(aicken)      
引用n216:
1.“一个字段算4个字节,100万条=4*100*10000字节=4M”----为何算4字节?
2.“你说的实验的目的是什么,就决定你的样本是什么,如果要测试大数据量数据或海量数据,100万条是不够的,100万条还不是大数据量的一个起点,大数据量起点一般要在千万级以上,而且数据库容量要在G级(字段字节总数*记录数。且不考虑索引等开销)。”----我读不出你想说什么。。。我只是向大家说明了100万条数据的导入SQL的极限最好成绩,仅此而已。你那些什么G级数据库,千万条数据,如果真的这么做了,无非是改个题目:“1000万数据导入数据库40秒”,事实上千万条数据的实验也做了,可是这有什么...


拿来一个T级数据库做数据导入测试,和一个新建的数据库做测试,我想新建的数据库更能说明导入的数据量与所用时间的关系。
我希望的实验环境,是排除其他影响因素的环境,不是秀我的T级数据库

 回复 引用 查看   
#40楼[楼主] 2010-03-18 16:26 | 李鸣(aicken)      
引用其实我是支持这位兄弟的。在这个方面楼主确实是“小学生”。
我的入库程序,都是单线程的批量入库。
服务器端需要做一定优化,尤其是oracle,不要让log file sync占用了主要时间,表结构决定了更多,比如物理存储结构,比如索引结构数量,等等,等等。
还有,就是持续的时间,比如有些方法,感觉很快,但是不具有可持续性,你会发现越来越慢,越来越慢。

了解了数据库的工作方式,我想,这些都不是问题。

哎,小学生就小学生吧,没能力把简单的问题搞得这么复杂。
我希望的实验环境,是排除其他影响因素的环境,只想说明在不受其他因素影响的前提下,数据量与时间的关系。至于你说的数据库优化是无完结的,在我看来这个实验中谈数据库优化,纯粹的口水仗!

 回复 引用 查看   
#41楼 2010-03-18 16:32 | 柳絮随风      
我纯粹是路过的。。。
 回复 引用 查看   
#42楼 2010-03-18 16:34 | 古道      
趁这里DBA比较多,赶快问个问题?
如果日志数据特别多,怎么存储,不影响按时间或字段查询效率?
先谢过!

 回复 引用 查看   
#43楼[楼主] 2010-03-18 16:44 | 李鸣(aicken)      
引用blackcat:
引用其实我是支持这位兄弟的。在这个方面楼主确实是“小学生”。
我的入库程序,都是单线程的批量入库。
服务器端需要做一定优化,尤其是oracle,不要让log file sync占用了主要时间,表结构决定了更多,比如物理存储结构,比如索引结构数量,等等,等等。
还有,就是持续的时间,比如有些方法,感觉很快,但是不具有可持续性,你会发现越来越慢,越来越慢。

了解了数据库的工作方式,我想,这些都不是问题。

而且,SQL SERVER,一个空表一个字段,100条数据,怎样优化才能突破4秒?请赐教一下。
 回复 引用 查看   
#44楼[楼主] 2010-03-18 16:49 | 李鸣(aicken)      
引用古道:
趁这里DBA比较多,赶快问个问题?
如果日志数据特别多,怎么存储,不影响按时间或字段查询效率?
先谢过!

偶不是DBA,不过日志不影响查询效率。。。
按时间或字段查询,字段内容无重复的话,SQL中建聚集索引,Oracle建立B树索引,不过Oracle中是默认的

 回复 引用 查看   
#45楼 2010-03-18 17:16 | blackcat      
@李鸣(aicken)
引用李鸣(aicken):
引用其实我是支持这位兄弟的。在这个方面楼主确实是“小学生”。
我的入库程序,都是单线程的批量入库。
服务器端需要做一定优化,尤其是oracle,不要让log file sync占用了主要时间,表结构决定了更多,比如物理存储结构,比如索引结构数量,等等,等等。
还有,就是持续的时间,比如有些方法,感觉很快,但是不具有可持续性,你会发现越来越慢,越来越慢。

了解了数据库的工作方式,我想,这些都不是问题。

哎,小学生就小学生吧,没能力把简单的问题搞得这么复杂。
我希望的实验环境,是排除其他影响因素的环境,只想说明在不受其他因素影响的前提下,数据量与时间的关系。至于你说的数据库优化是无完结的,在我看来这个实验中谈数据库优化,纯粹的口水仗!


你的服务端什么都不说的话,你这个测试,说4秒百万,没有什么参考价值。如果用相对数字评价你实验中各种方法的性能,这个数据可以用,关键是比例,但是没有必要突出4秒百万这个事情。
不是说小学生不好哈,我是按照楼上那个思路顺下来的。
见谅,莫急。
我收回小学生的相关话语。

 回复 引用 查看   
#46楼 2010-03-18 17:25 | blackcat      
@李鸣(aicken)
引用李鸣(aicken):
引用blackcat:
引用其实我是支持这位兄弟的。在这个方面楼主确实是“小学生”。
我的入库程序,都是单线程的批量入库。
服务器端需要做一定优化,尤其是oracle,不要让log file sync占用了主要时间,表结构决定了更多,比如物理存储结构,比如索引结构数量,等等,等等。
还有,就是持续的时间,比如有些方法,感觉很快,但是不具有可持续性,你会发现越来越慢,越来越慢。

了解了数据库的工作方式,我想,这些都不是问题。

而且,SQL SERVER,一个空表一个字段,100条数据,怎样优化才能突破4秒?请赐教一下。


赐教两字太重。请收回。
然后什么服务器,请说明,同时sqlserver的数据文件配置请说明。
不过可以从存储来考虑。
刚才那个哥们说的挺好,IO密集型应用,单进程问题。
使用多路数据库文件,条带化存储,数据量建议从千万起测试。
还有,不知道bcp,你试过没有。

 回复 引用 查看   
#47楼 2010-03-18 17:30 | blackcat      
@古道
什么日志数据?
不要告诉是数据库自身的日志。

 回复 引用 查看   
#48楼 2010-03-18 18:03 | Muse      
我们的系统导入10万数据都要几个小时,上百万的时候可能要1、2天才行。
我还以为找到了什么高级东西了,唉~~还是没办法!

 回复 引用 查看   
#49楼[楼主] 2010-03-18 19:22 | 李鸣(aicken)      
引用
blackcat:
你的服务端什么都不说的话,你这个测试,说4秒百万,没有什么参考价值。如果用相对数字评价你实验中各种方法的性能,这个数据可以用,关键是比例,但是没有必要突出4秒百万这个事情。
不是说小学生不好哈,我是按照楼上那个思路顺下来的。
见谅,莫急。
我收回小学生的相关话语。

如文章一开始所介绍的:
本实验中所用到工具为VS2008和SQL SERVER 2000、SQL SERVER 2008,分别使用5中方法将100万条数据导入SQL 2000与SQL 2008中,实验环境是DELL 2850双2.0GCPU,2G内存的服务器。感兴趣的朋友可以下载源代码自己验证一下所用时间。

关于“4秒百万”:有一些读者对这一点很有兴趣,他们的意见主要分为2部分。1.应当基于一个“TB级的大数据库”进行测试。2.应当基于千万条数据、多字段经行测试。
其实,我考虑到1.该实验首先要尽可能的排除干扰,只将关心的数据量与时间的因素反映出来,所以没有使用TB级的数据库。2.百万起点也好,千万起点也罢,不同的只是时间,说明的问题是一至的。而且千万的试验也做了,但只发布了百万的结果,因为我觉得“百万4秒”已经足以说明问题,并且感兴趣的网友自可以在百万的基础上优化,突破4秒就是进步。
即使使用千万的数据进行测试,也会有人说亿级的数据好,而且你觉得把题目改成“千万40秒”就没人跳出来说不是了吗?
正如我刚说的,“百万4秒”与“千万40秒”,只是一个前提条件与结果的关系,它所反映的是一种技术的能力,我们所要关心的是这种技术本身,无论借助百万还是千万,说明的也是这种技术,这就足够了。 无论你突破4秒还是40秒,都是进步。

 回复 引用 查看   
#50楼[楼主] 2010-03-18 19:32 | 李鸣(aicken)      
引用blackcat:
@李鸣(aicken)
引用李鸣(aicken):
引用blackcat:
引用其实我是支持这位兄弟的。在这个方面楼主确实是“小学生”。
我的入库程序,都是单线程的批量入库。
服务器端需要做一定优化,尤其是oracle,不要让log file sync占用了主要时间,表结构决定了更多,比如物理存储结构,比如索引结构数量,等等,等等。
还有,就是持续的时间,比如有些方法,感觉很快,但是不具有可持续性,你会发现越来越慢,越来越慢。

了解了数据库的工作方式,我想,这些都不是问题。

而且,SQL SERVER,一个空表一个字段,100条数据,怎样优化才能突破4秒?请赐教一下。


赐教两字太重。请收回。
然后什么服务器,请说明,同时sqlserver的数据文件配置请说明。
不过可以从存储来考虑。
刚才那个哥们说的挺好,IO密集型应用,单进程问题。
使用多路数据库文件,条带化存储,数据量建议从千万起测试。
还有,不知道bcp,你试过没有。



数据库端没有做任何优化,就像文章中介绍的,一个空表一个字段。
关于数据文件,只有一个。除非你能人为的控制SQL SERVER使用哪个数据文件接收数据,否则在此实验中,优化I/O也就无从谈起。
而表分区,固然是不错的方法,但是对于SQL 2000是没有表分区的,所以在最简单的环境下,尽量通过优化程序,提升导入效率。

如文章一开始所介绍的:实验环境是DELL 2850双2.0GCPU,2G内存的服务器。感兴趣的朋友可以下载源代码自己验证一下所用时间。

 回复 引用 查看   
#51楼[楼主] 2010-03-18 19:35 | 李鸣(aicken)      
引用Muse:
我们的系统导入10万数据都要几个小时,上百万的时候可能要1、2天才行。
我还以为找到了什么高级东西了,唉~~还是没办法!

能介绍一下具体情况吗?
我们的系统在Oracle之间导数据,每1千万条20分钟完成,是C写的东西

 回复 引用 查看   
#52楼 2010-03-18 20:05 | WinCE界面      
Windows系统(包括WinCE,Windows Mobile,Windows Phone)应用界面开发:
1.VC/EVC/MFC/C#界面;
2.源码全开放,可自由修改和发放,提供支持多平台编译的源码;
3.界面代码丰富,如:GPS导航界面、常用工控类界面;
4.分类明确,可以快速找到您需要的代码功能与模块;
5.嵌入式代码支持WINCE,Windows Mobile等平台,可用于手机,移动终端等设备。
6.部分代码采用WIN32 SDK编写,速度快,效率高,界面漂亮。
7.GIF图片显示;
8.PNG图片透明显示;
9.PNG按钮,界面等;
10.WINCE游戏小软件等;

*可提供需求,定制漂亮的UI程序界面,代码可靠,周期短。

详细请访问:
http://www.evccode.com

 回复 引用 查看   
#53楼 2010-03-18 20:30 | blackcat      
引用李鸣(aicken):
引用
blackcat:
你的服务端什么都不说的话,你这个测试,说4秒百万,没有什么参考价值。如果用相对数字评价你实验中各种方法的性能,这个数据可以用,关键是比例,但是没有必要突出4秒百万这个事情。
不是说小学生不好哈,我是按照楼上那个思路顺下来的。
见谅,莫急。
我收回小学生的相关话语。

如文章一开始所介绍的:
本实验中所用到工具为VS2008和SQL SERVER 2000、SQL SERVER 2008,分别使用5中方法将100万条数据导入SQL 2000与SQL 2008中,实验环境是DELL 2850双2.0GCPU,2G内存的服务...


说了半天,能告诉我什么存储吗?怎么配置?文件io大概是什么状况?
还有多路数据文件关分区什么事情?

还有关于说的那个百万4秒这个事情,我说了,那个值没有意义,比如一个金融行业的数据库TB级别fts,2s搞定,你说这个有意义吗?

 回复 引用 查看   
#54楼 2010-03-18 20:36 | blackcat      
时间这个问题,估计还是说不服你。记得有个人写oracle入库方式和性能比较的帖子,你可以找找看。那个人的帖子和你测试差不多同样的东西,但是绝对不会让我们这么争论这个问题。
 回复 引用 查看   
#55楼 2010-03-18 20:42 | blackcat      
引用Muse:
我们的系统导入10万数据都要几个小时,上百万的时候可能要1、2天才行。
我还以为找到了什么高级东西了,唉~~还是没办法!


这个显然是有问题的。一个表,单记录定长大概2000字节,五个索引,一个主键约束,无触发器;测试服务器cpu主频2.8,数据文件在一个硬盘上,默认oracle安装方式,oracle本身不做任何优化,每秒8000的速度大概可以持续4天左右,之后略慢,但是,按你那十万数据,用不了几秒的。

可以先检查先文件io,再说其他。要不找个dba看看。

sqlserver和sybase的话,大概能到3K,同样配置。

 回复 引用 查看   
#56楼 2010-03-18 21:13 | blackcat      
最后一句:
你说单线程批量插入,是最好的方式,我绝对同意,可以避免服务器多余操作,并且降低文件等资源竞争;但是挑战极限,100万4秒,我不同意,这个值只对你的机器起作用,更不是极限。

 回复 引用 查看   
#57楼 2010-03-18 22:22 | n216      
引用blackcat:
最后一句:
你说单线程批量插入,是最好的方式,我绝对同意,可以避免服务器多余操作,并且降低文件等资源竞争;但是挑战极限,100万4秒,我不同意,这个值只对你的机器起作用,更不是极限。

同意!不过你说了他也不懂!

 回复 引用 查看   
#58楼 2010-03-18 22:40 | n216      
我还是忍不住,用VFP来插入100万条记录。
什么优化都不用,结果不到1秒

表名:f1
字段名:f1 整型

运行环境:联想R60

程序:
SET TALK OFF
thisform.label1.Caption=TTOC(DATETIME())
SELECT f1
FOR i=1 TO 1000000
APPEND BLANK
replace f1 WITH i
ENDFOR
thisform.label2.Caption=TTOC(DATETIME())
结果:1秒(不太精确,估计小于1秒)

结论:100万条记录花4秒,时间太长了。那里是个极限呀!


 回复 引用 查看   
#59楼 2010-03-18 22:47 | n216      
我用相同的程序将100万,改成了1000万!
结果花了:5秒!

 回复 引用 查看   
#60楼 2010-03-19 01:05 | Jeffrey Hua      
This kind of test is useless.
Try to create a table with index.And then test the time.

 回复 引用 查看   
#61楼[楼主] 2010-03-19 09:03 | 李鸣(aicken)      
引用n216:
我还是忍不住,用VFP来插入100万条记录。
什么优化都不用,结果不到1秒

表名:f1
字段名:f1 整型

运行环境:联想R60

程序:
SET TALK OFF
thisform.label1.Caption=TTOC(DATETIME())
SELECT f1
FOR i=1 TO 1000000
APPEND BLANK
replace f1 WITH i
ENDFOR
thisform.label2.Caption=TTOC(DATETIME())
结果:1秒(不太精确,估计小于1秒)

结论:100万条记录花4秒,时间太长了。那里是个极限呀!



你要是忍不住就遵守挑战的规则,用.Net写个程序来试试,VPF那个上世纪数据库一体的东东当然快了

 回复 引用 查看   
#62楼[楼主] 2010-03-19 09:05 | 李鸣(aicken)      
引用n216:
引用blackcat:
最后一句:
你说单线程批量插入,是最好的方式,我绝对同意,可以避免服务器多余操作,并且降低文件等资源竞争;但是挑战极限,100万4秒,我不同意,这个值只对你的机器起作用,更不是极限。

同意!不过你说了他也不懂!


哎,没你懂得多,领教了领教了。。。

 回复 引用 查看   
#63楼 2010-03-19 09:30 | blackcat      
引用Jeffrey Hua:
This kind of test is useless.
Try to create a table with index.And then test the time.

but, someone think this is useful;

 回复 引用 查看   
#64楼 2010-03-19 11:26 | doylecnn      
再说一遍,实验的目的是考察一定量数据的最佳时间,100万换成1000万只是时间不同了,说明的问题都一样!

果然是小学生,还没领会到量变导致质变的问题

 回复 引用 查看   
#65楼[楼主] 2010-03-19 20:47 | 李鸣(aicken)      
引用blackcat:
引用Jeffrey Hua:
This kind of test is useless.
Try to create a table with index.And then test the time.

but, someone think this is useful;


blackcat,我正式警告你,说事勿评人!你如果三番五次的如此不友好,那就别怪别人以眼还眼了!

 回复 引用 查看   
#66楼[楼主] 2010-03-19 20:47 | 李鸣(aicken)      
@blackcat
blackcat,我正式警告你,说事勿评人!你如果三番五次的如此不友好,那就别怪别人以眼还眼了!

 回复 引用 查看   
#67楼 2010-03-19 21:12 | blackcat      
引用李鸣(aicken):
引用blackcat:
引用Jeffrey Hua:
This kind of test is useless.
Try to create a table with index.And then test the time.

but, someone think this is useful;


blackcat,我正式警告你,说事勿评人!你如果三番五次的如此不友好,那就别怪别人以眼还眼了!


拜托,看回复时间。

 回复 引用 查看   
#68楼 2010-03-22 11:15 | pk的眼泪      
这个LZ不太谦虚。。
 回复 引用 查看   
#69楼[楼主] 2010-03-23 16:49 | 李鸣(aicken)      
现在我把已有的方案连接放在这里,关于这个实验,有几位网友给我发邮件,向我要征集到的方案,现在我把已有的方案连接放在这里,感兴趣的可以下载,我就不一一回复了。
而关注数据库方面的网友,恐怕要让你们失望了,就像我说过数遍的原因,数据库的优化度量起来难度比较大,假如你今天说要分布
数据文件,明天说要做分区表,后天说要个盘阵环境分布I/O,这种优化是很难度量的,已经脱离了本实验的目的,而且这些都是最
基础的知识,有一些经验的人都知道,没必要这这里反复“提醒”我,我们的关注点不同罢了,除了通过数据库优化提升效率外,程
序方面可做的事情还有很多。
还是那句话,一个人的真正水平不是看他的博客,而是看他对其他博客的评论内容,在这里劝大家,踏实做事,勿议他人!

感谢“孔明”网友的支持:“insert into select”方法运行5次,最好成绩为6秒
感谢“于爱武”网友的支持:Oracle数据库的外部表速度的确不凡!
感谢“可以不可以”网友的支持:你的方法似乎运行不了,我打包在一个solution里了,你核对一下

以上网友如果需要屏幕录像证明运行时间,可以再联系我,谢谢!

SQL SERVER方案合集:http://files.cnblogs.com/isline/sqltest1.rar
Oracle方案:http://files.cnblogs.com/isline/Oracle.rar
另外,我的同事还为此写了一篇SQL SERVER与Oracle对比的文章,预约发在6月的《软件报》上,请有兴趣的网友关注!

 回复 引用 查看   
#70楼 2010-04-13 11:26 | 我和日子互混      
又引发口水战,飘过~~!!!
 回复 引用 查看   
#71楼 2010-06-23 21:58 | 源姜      
飘来飘去,我过来看看的。听说这里打口水战。
水平低的拿现有的技术说事儿,水平高点儿的拿别不不知道的现有的技术说事儿。

怎么就能掐到一块儿呢?做技术的悲哀啊

 回复 引用 查看   
#72楼 2010-08-31 20:00 | Ran Ran      
实践出真知。
 回复 引用 查看   
#73楼 2010-08-31 22:41 | yi      
当你导入三亿条数据进入一张表再试试看,另外要有聚集索引和非聚集索引,如果只是只导数据,DTS就足够了,不需要我来写程序
 回复 引用 查看   
#74楼 2010-09-01 15:15 | YnioBa      
楼主你好,请问那个SQL.TXT的文件是怎么生成的?插入的时候,如何对应表里面的字段。。
 回复 引用 查看   
#75楼 2010-12-10 15:20 | itom      
有很大帮助
 回复 引用 查看   
#76楼 2011-01-14 15:53 | john23.net      
有帮助
 回复 引用 查看   
#77楼 2011-02-09 15:41 | 且行且思      
n216大哥说的对,100万测试不是海量....
对于dba而言,真正考验的是select ,

 回复 引用 查看   
#78楼 2011-03-28 16:02 | HelloJeep      
楼主的分享、奉献精神应该值得大家学习,楼主是做学问的;而那两位,夸夸其谈不知所云。

 回复 引用 查看   
#79楼 2011-04-15 08:37 | super mans      
采用该方法为什么我的ExecuteNonQuery()无法将类型为 System.String 的对象强制转换为类型 System.Array有这样的异常!!!
 回复 引用 查看   
#80楼 2011-11-23 15:20 | LS.Eye      
都是纸上谈兵,没有真正运用到项目体验中,2008怎么都不比2000差,一台机子上安装2000,再安装2008,2008服务端口可能还是2000的端口号根本没发挥出08功能等等设置、好好研究下2008
 回复 引用 查看   
缘清 aicken

 



名:缘( aicken)
MSN & EMAILaicken@live.cn


开大学软工程硕士
研究.Net与企

“软件报”“IT专家网”约撰稿人

我的MVP配置

我的新浪
像影随心

昵称:Aicken(李鸣)
园龄:3年1个月
粉丝:78
关注:7

搜索

 

常用链接

我的标签

随笔分类(115)

随笔档案(104)

积分与排名

  • 积分 - 262657
  • 排名 - 284

阅读排行榜

评论排行榜

推荐排行榜