CSDN密碼庫窺視各大數據庫性能


很多同學一直抱怨手頭木有一個真實的數據庫,無法進行數據庫性能試驗,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,內容如下:

UNRECOVERABLE
LOAD DATA
INFILE 'D:\CSDN\www.csdn.net.sql'
INSERT into table CSDN
fields terminated by '#'
(
ID,
PWD,
EMAIL
)

           然后使用sqlldr工具:

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

          輸出文件為resulthis.out:

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行的導入效率,很不錯。
 

MySQL

       MySQL導入比較簡單,不需要CTRL文件,直接在mysql命令行執行即可。

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中打印信息。

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

             輸出文件為OUT.LOG:

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沒有進行相關的設置,使用了默認配置。

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的執行計划:

執行計划
----------------------------------------------------------
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是否能利用這個索引。

SQL> CREATE INDEX I1 ON CSDN(PWD);

索引已創建。

已用時間:  00: 00: 27.17

         查看下執行計划:

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,執行如下語句:

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。

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了...

        查看下執行計划:

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同時支持查看每個執行節點的執行時間:

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了。

       下面創建索引試下:

CREATE INDEX I1 ON CSDN(PWD);

time used: 25562.295(ms) clock tick:1959731992. Execute id is 1.

       首先看下執行計划是否改變,如果沒變的話,我們就不需要再去執行看時間了:

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,看下這個新的執行計划是否是最好的。

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^_^


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM