zoukankan      html  css  js  c++  java
  • CSDN密码库窥视各大数据库性能

    CSDN密码库窥视各大数据库性能

    2011-12-26 17:30 by 心中无码, 1076 visits, 收藏编辑

    很多同学一直抱怨手头木有一个真实的数据库,无法进行数据库性能试验,CSDN得知了同学们的苦恼,立刻开放了部分数据库,供同学们学习、参考,对CSDN这种大公无私、舍己为人的行为,有关部门对此进行了高度的赞扬,下面就带领同学们来进行一个小小的性能对比测试。

     

            实验选择了三个数据库:Oracle11g、MySQL5.1以及DM7。Oracle作为商业数据库大哥大的代表,MySQL作为开源数据库的代表,DM7很多同学估计就不清楚了(达梦数据库),暂时作为国产数据库的代表吧(同学们轻拍^_^)。

    测试环境

    OS WINDOWS XP SP3
    CPU Intel i3 530 @2.93GHz
    MEMORY 4G
    ORACLE 11.1.0.6.0
    MySQL 5.1.30
    DM V7

    导入数据库性能测试

               这次CSDN泄漏的密码库规模说大不大,说小不小,600多万行(CSDN的用户数霸气外漏,博客园有多少呢?),同学们测试的福音啊。还好我第一时间download了,CSDN的处理还是比较迅速的,很快网上的下载链接就失效了,赞一个。这个密码库是一个文本文件,200多M,用UE打开还要等一会...每行的格式如下:

    用户名 # 密码 # 邮箱

            三个字段间的间隔是’空格#空格’,为了方便导入数据库,我们使用UE将其分割符全部替换为#。

             肿么导入数据库呢?上面选的三个数据库都具有快速导入的工具,Oralce提供了sqlldr工具,MySQL提供了load data命令,DM7提供了dmfldr工具,dmfldr和sqlldr工具感觉使用起来比较相似,MySQL提供的load data作为一种SQL命令。

    建表

            导入之前我们需要创建一个空表,Oracle和DM7的建表语句如下:

    CREATE TABLE CSDN(ID VARCHAR(256), PWD VARCHAR(256), EMAIL VARCHAR(256));

               MySQL的建表语句我们指定存储引擎为INNODB

    CREATE TABLE CSDN(ID VARCHAR(256), PWD VARCHAR(256), EMAIL VARCHAR(256)) ENGINE=INNODB;

             初始建表语句这里不指定任何索引。   

    装载数据

      ORACLE

                首先创建控制文件ora_csdn.ctrl,内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    UNRECOVERABLE
    LOAD DATA
    INFILE 'D:\CSDN\www.csdn.net.sql'
    INSERT into table CSDN
    fields terminated by '#'
    (
    ID,
    PWD,
    EMAIL
    )

               然后使用sqlldr工具:

    1
    sqlldr userid=SYSMAN/SYSDBA control=D:/CSDN/ora_csdn.ctrl DIRECT=TRUE log=resulthis.out

              输出文件为resulthis.out:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    SQL*Loader: Release 11.1.0.6.0 - Production on 星期六 12月 24 16:01:06 2011
     
    Copyright (c) 1982, 2007, Oracle.  All rights reserved.
     
    控制文件:      D:/CSDN/ora_csdn.ctrl
    数据文件:      D:\CSDN\www.csdn.net.sql
      错误文件:    D:/CSDN/www.csdn.net.bad
      废弃文件:    未作指定
      
    (可废弃所有记录)
     
    要加载的数: ALL
    要跳过的数: 0
    允许的错误: 50
    继续:    未作指定
    所用路径:       直接
     
     
    加载是 UNRECOVERABLE;产生无效的恢复操作。
     
    表 CSDN,已加载从每个逻辑记录
    插入选项对此表 INSERT 生效
     
       列名                        位置      长度  中止 包装数据类型
    ------------------------------ ---------- ----- ---- ---- ---------------------
    ID                                  FIRST     *   #       CHARACTER           
    PWD                                  NEXT     *   #       CHARACTER           
    EMAIL                                NEXT     *   #       CHARACTER           
     
     
    表 CSDN:
      6428632 行 加载成功。
      由于数据错误, 0 行 没有加载。
      由于所有 WHEN 子句失败, 0 行 没有加载。
      由于所有字段都为空的, 0 行 没有加载。
     
    在直接路径中没有使用绑定数组大小。
    列数组  行数:    5000
    流缓冲区字节数:  256000
    读取   缓冲区字节数: 1048576
     
    跳过的逻辑记录总数:          0
    读取的逻辑记录总数:       6428632
    拒绝的逻辑记录总数:          0
    废弃的逻辑记录总数:        0
    由 SQL*Loader 主线程加载的流缓冲区总数:     1497
    由 SQL*Loader 加载线程加载的流缓冲区总数:        0
     
    从 星期六 12月 24 16:01:06 2011 开始运行
    在 星期六 12月 24 16:01:13 2011 处运行结束
     
    经过时间为: 00: 00: 06.93
    CPU 时间为: 00: 00: 04.65
    从输出文件可以看出时间为00:00:06.93,将近每秒钟100W行的导入效率,很不错。
    1
      

    MySQL

           MySQL导入比较简单,不需要CTRL文件,直接在mysql命令行执行即可。

    1
    2
    3
    4
    mysql> LOAD DATA local infile "D:/CSDN/www.csdn.net.sql" into table CSDN fields
    terminated by '#';
    Query OK, 6428632 rows affected, 14275 warnings (1 min 51.95 sec)
    Records: 6428632  Deleted: 0  Skipped: 0  Warnings: 14275

           从打印信息,可以看出,耗时接近2分钟,性能较差。

    DM7

             DM7提供了dmfldr.exe工具,需要ctrl文件,用法和oracle基本类似,有些细微的差别,比如指定输出导入到输出文件,还是会在CMD中打印信息。

    1
    2
    D:\SRC\DM7\Release>dmfldr.exe USERID=SYSDBA/SYSDBA CONTROL='D:/CSDN/dm_csdn.ctrl
    ' DIRECT=TRUE  LOG='OUT.LOG'

                 输出文件为OUT.LOG:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    dmfldr:
     
    Copyright (c) 2011, 2015, Dameng.  All rights reserved.
     
    控制文件:D:/CSDN/dm_csdn.ctrl
     
    加载行数:全部
     
    每次提交服务器行数:50000
     
    跳过行数:0
     
    允许错误数:100
     
    是否直接加载:是
     
    是否插入自增列:否
     
    数据是否已按照聚集索引排序:否
     
    字符集:GBK
     
     
    数据文件共1个:
    D:\CSDN\www.csdn.net.sql
     
    错误文件:fldr.bad
     
    目标表:CSDN
     
    列名                                                                                                                            终止    包装数据类型       
    ID                                                                                                                               WHT      CHARACTER          
    PWD                                                                                                                              WHT      CHARACTER          
    EMAIL                                                                                                                            WHT      CHARACTER          
     
    目标表 CSDN :
    6428632行 加载成功。
    由于数据格式错误,0行 丢弃。
    由于数据错误,0行 没有加载。
     
    跳过的逻辑记录总数:0
    读取的逻辑记录总数:6428632
    拒绝的逻辑记录总数:0
     
    用时:15238.166(ms)

             查看输出文件,用时15s,比MySQL好很多,比Oralce差一点。

    聚集函数性能测试

                这里的测试我们使用网上用来统计密码使用次数TOP 10的语句,大家都知道Oracle没有TOP N,取而代之的是ROWNUM,MySQL也没有TOP N,取而代之的是LIMIT,DM7支持TOP N、ROWNUM和LIMIT三种语法。所有的测试都关闭了结果集重用

    ORACLE

                 Oracle没有进行相关的设置,使用了默认配置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    SQL> SELECT  CNT, PWD FROM (SELECT COUNT(PWD) as cnt, PWD FROM CSDN GROUP BY PWD
     ORDER BY COUNT(PWD) DESC ) WHERE ROWNUM < 11;
     
           CNT PWD
    ---------- --------------------
        235017 123456789
        212759 12345678
         76348 11111111
         46053 dearbook
         34953 00000000
         20010 123123123
         17793 1234567890
         15033 88888888
          6995 111111111
          5965 147258369
     
    已选择10行。
     
    已用时间:  00: 00: 11.09

              ORACLE用时11S,我们来看下Oracle的执行计划:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    执行计划
    ----------------------------------------------------------
    Plan hash value: 3269342783
     
    --------------------------------------------------------------------------------
     
    | Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     |
     
    --------------------------------------------------------------------------------
     
    |   0 | SELECT STATEMENT        |      |    10 |  1430 | 11354   (5)| 00:02:17 |
     
    |*  1 |  COUNT STOPKEY          |      |       |       |            |          |
     
    |   2 |   VIEW                  |      |  6856K|   935M| 11354   (5)| 00:02:17 |
     
    |*  3 |    SORT ORDER BY STOPKEY|      |  6856K|   850M| 11354   (5)| 00:02:17 |
     
    |   4 |     HASH GROUP BY       |      |  6856K|   850M| 11354   (5)| 00:02:17 |
     
    |   5 |      TABLE ACCESS FULL  | CSDN |  6856K|   850M| 10890   (1)| 00:02:11 |
     
    --------------------------------------------------------------------------------
     
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       1 - filter(ROWNUM<11)
       3 - filter(ROWNUM<11)
     
    Note
    -----
       - dynamic sampling used for this statement
     
     
    统计信息
    ----------------------------------------------------------
            133  recursive calls
              0  db block gets
          39767  consistent gets
          56161  physical reads
              0  redo size
            684  bytes sent via SQL*Net to client
            416  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
             10  rows processed

              执行计划可以看出来,由于没有索引,首先进行了全表扫描,然后根据PWD进行HASH,按照COUNT进行SORT,构建一个临时的VIEW,然后是过滤rownum<11。

           下面对PWD列创建索引,看下Oracle是否能利用这个索引。

    1
    2
    3
    4
    5
    SQL> CREATE INDEX I1 ON CSDN(PWD);
     
    索引已创建。
     
    已用时间:  00: 00: 27.17

             查看下执行计划:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    SQL> SELECT  CNT, PWD FROM (SELECT COUNT(PWD) as cnt, PWD FROM CSDN GROUP BY PWD
     ORDER BY COUNT(PWD) DESC ) WHERE ROWNUM < 11;
     
    已选择10行。
     
    已用时间:  00: 00: 10.31
     
    执行计划
    ----------------------------------------------------------
    Plan hash value: 3269342783
     
    --------------------------------------------------------------------------------
     
    | Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     |
     
    --------------------------------------------------------------------------------
     
    |   0 | SELECT STATEMENT        |      |    10 |  1430 | 11354   (5)| 00:02:17 |
     
    |*  1 |  COUNT STOPKEY          |      |       |       |            |          |
     
    |   2 |   VIEW                  |      |  6856K|   935M| 11354   (5)| 00:02:17 |
     
    |*  3 |    SORT ORDER BY STOPKEY|      |  6856K|   850M| 11354   (5)| 00:02:17 |
     
    |   4 |     HASH GROUP BY       |      |  6856K|   850M| 11354   (5)| 00:02:17 |
     
    |   5 |      TABLE ACCESS FULL  | CSDN |  6856K|   850M| 10890   (1)| 00:02:11 |
     
    --------------------------------------------------------------------------------
     
     
    Predicate Information (identified by operation id):
    ---------------------------------------------------
     
       1 - filter(ROWNUM<11)
       3 - filter(ROWNUM<11)
     
    Note
    -----
       - dynamic sampling used for this statement
     
     
    统计信息
    ----------------------------------------------------------
            133  recursive calls
              0  db block gets
          39776  consistent gets
          32748  physical reads
              0  redo size
            684  bytes sent via SQL*Net to client
            416  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
             10  rows processed
    可以看到时间并没有提升,ORACLE并没有利用到索引

    MySQL

           MySQL设置了INNODB的BUFFER大小为700M,执行如下语句:

    1
    SELECT PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(PWD) DESC LIMIT 10;

          长时间木有相应啊,打了俩小时羽毛球回来,还是没执行完....

          设置了SROT BUFFER后仍无效果,尝试创建索引,发现很慢,慢到简直就是挑战我的极限,so close it。INNODB的测试结果有些失望,可能是我设置的参数不够,希望有经验的同学尝试下,指点下~~。

    DM7

                  DM7设置了BUFFER大小也为700M。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    SELECT TOP 10 PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(PWD) DESC;
    PWD             COUNT(PWD)
     
    1       123456789       235029
     
    2       12345678        212761
     
    3       11111111        76348
     
    4       dearbook        46053
     
    5       00000000        34953
     
    6       123123123       20010
     
    7       1234567890      17794
     
    8       88888888        15033
     
    9       111111111       6995
     
    10      147258369       5966
    10 rows got
    time used: 12186.676(ms) clock tick:1383768307. Execute id is 1.

         执行时间为12S,第二次和第三次执行时,时间会缩短为7S左右,因为数据全部缓存在buffer中,没有I/O。有同学可能发现和oracle比较有些count计算不一致,这是因为存在一些密码结尾为空格的数据,DM的处理在这里类似SQL SERVER了...

            查看下执行计划:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SQL>EXPLAIN SELECT TOP 10 PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(
    PWD) DESC;
    EXPLAIN SELECT TOP 10 PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(PWD)
     DESC;
     
    #NSET2: [0, 0, 0]
      #PRJT2: [0, 0, 0]; exp_num(2), is_atom(FALSE)
        #SORT3: [0, 0, 0]; key_num(1), is_distinct(FALSE)
          #HAGR2: [0, 0, 0]; grp_num(1), sfun_num(2)
            #CSCN2: [2721, 6428632, 0]; INDEX33555437(CSDN)
    time used: 0.732(ms) clock tick:2138943. Execute id is 0.

             可以看出,DM7也首先进行了全表扫描SCAN,然后针对GROUP BY执行了HASH AGR,针对ORDER BY执行了SORT节点。

           DM7同时支持查看每个执行节点的执行时间:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    SQL>select n.name, time_used, n_enter from v$sql_node_name n, v$sql_node_history
     h where n.type$ = h.type$ and exec_id = 1 order by seq_no;
    select n.name, time_used, n_enter from v$sql_node_name n, v$sql_node_history h w
    here n.type$ = h.type$ and exec_id = 1 order by seq_no;
    NAME            TIME_USED               N_ENTER
     
    1       DLCK    2       2
     
    2       NSET2   71      3
     
    3       PRJT2   2       4
     
    4       SORT3   470170  4038
     
    5       HAGR2   6467980 10466
     
    6       CSCN2   5222702 6430
    6 rows got
    time used: 15.969(ms) clock tick:46813291. Execute id is 4.

            这个比较方便了,可以知道性能瓶颈是在哪个执行节点,如果实在CSCN,那就是I/O的问题了,如果是HAGR或者是SORT,那可能就需要调整下相应的BUFFER了。

           下面创建索引试下:

    1
    2
    3
    CREATE INDEX I1 ON CSDN(PWD);
     
    time used: 25562.295(ms) clock tick:1959731992. Execute id is 1.

           首先看下执行计划是否改变,如果没变的话,我们就不需要再去执行看时间了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SQL>EXPLAIN SELECT TOP 10 PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(
    PWD) DESC;
    EXPLAIN SELECT TOP 10 PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(PWD)
     DESC;
     
    #NSET2: [0, 0, 0]
      #PRJT2: [0, 0, 0]; exp_num(2), is_atom(FALSE)
        #SORT3: [0, 0, 0]; key_num(1), is_distinct(FALSE)
          #SAGR2: [0, 0, 0]; grp_num(1), sfun_num(2)
            #SSCN: [928, 6428632, 0]; I1(CSDN)
    time used: 0.459(ms) clock tick:1340375. Execute id is 0.

             执行计划发生了变化,可以看到SSCN里面是使用了I1索引,同时HAGR也改为了SAGR,看下这个新的执行计划是否是最好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    SQL>SELECT TOP 10 PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(PWD) DES
    C;
    SELECT TOP 10 PWD, COUNT(PWD) FROM CSDN GROUP BY PWD ORDER BY COUNT(PWD) DESC;
    PWD             COUNT(PWD)
     
    1       123456789       235029
     
    2       12345678        212761
     
    3       11111111        76348
     
    4       dearbook        46053
     
    5       00000000        34953
     
    6       123123123       20010
     
    7       1234567890      17794
     
    8       88888888        15033
     
    9       111111111       6995
     
    10      147258369       5966
    10 rows got
    time used: 1897.215(ms) clock tick:1269554324. Execute id is 4.

           时间缩短为1897.215(ms),可以看到DM7在执行计划的选择上更加精确一点。

    小结

            通过上面简单的测试,可以看出在文本数据导入方面Oracle比较快,DM7紧随其后,MySQL就略显不足了。在聚集函数和排序处理方面,DM7的计划选择更加精确一点,Oracle表现中规中矩,MySQL的复杂查询一直是软肋,可能和插件式的存储引擎设计模式有关系,支持多种存储引擎导致其优化器的设计是比较通用,通用的结果就无法进行精确的优化。

            经过@CFR同学的提醒,进行了这个比较粗略的测试,从库的下载到导入到测试,还是花费了一点时间,发这个博文很纠结,怕同学说我是水文,最后声明下吧,以上数据均是实际测试结果。最后再次感谢下CSDN^_^

    踏着落叶,追寻着我的梦想。转载请注明出处
  • 相关阅读:
    【Codeforces 349B】Color the Fence
    【Codeforces 459D】Pashmak and Parmida's problem
    【Codeforces 467C】George and Job
    【Codeforces 161D】Distance in Tree
    【Codeforces 522A】Reposts
    【Codeforces 225C】Barcode
    【Codeforces 446A】DZY Loves Sequences
    【Codeforces 429B】Working out
    【Codeforces 478C】Table Decorations
    【Codeforces 478C】Table Decorations
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2302673.html
Copyright © 2011-2022 走看看