2012-01-13 54 views
1

*如果你是懶得看,你可以找到我的最終問題的說明...MySQL的插入性能stressTool

您好,我建立一個簡單的數據庫:

CREATE TABLE `users` (
    `id` varchar(45) NOT NULL, 
    `full_name` varchar(45) NOT NULL, 
    `first_name` varchar(45) NOT NULL, 
    `last_nmae` varchar(45) NOT NULL, 
    `login` varchar(45) NOT NULL, 
    `password` varchar(45) NOT NULL, 
    PRIMARY KEY (`id`,`full_name`,`login`), 
    UNIQUE KEY `idusers_UNIQUE` (`id`), 
    UNIQUE KEY `login_UNIQUE` (`login`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$ 

現在我測試插入單行的性能。

我用C#創建了一個壓力工具,並將其運行到1M行。 這是代碼,如果你有興趣:

abstract class Job 
    { 
     private static object synObject = new object(); 
     private static int _id = 0; 
     private static DateTime startingTime = DateTime.Now; 
     private const int JOB_PER_SIRCLE = 10; 

     protected int id; 
     public Job() 
     { 
      lock (synObject) 
      { 
       _id++; 
       id = _id; 
      } 
     } 

     public void run() 
     { 
      while (true) 
      { 
       for (int i = 0; i < JOB_PER_SIRCLE; i++) 
       { 
        doJob(); 
       } 
       lock (synObject) 
       { 
        calculate(); 
       } 
      } 
     } 

     private static DateTime lastLog = DateTime.Now; 
     private static long numOfJobsAcomplished = 0; 
     private static long totalNumOfJobsAcomplished = 0; 

     private static void calculate() 
     { 
      totalNumOfJobsAcomplished += JOB_PER_SIRCLE; 
      numOfJobsAcomplished += JOB_PER_SIRCLE; 
      DateTime now = DateTime.Now; 
      TimeSpan timePass = now - lastLog; 

      if (timePass.TotalSeconds > 1) 
      { 
       double total = 1000000; 
       TimeSpan speed = TimeSpan.FromMilliseconds(timePass.TotalMilliseconds/numOfJobsAcomplished * total); 
       Console.WriteLine("Speed = " + String.Format("{0:00.0000}", speed.TotalMinutes) + " Completed " + String.Format("{0:00.000}", totalNumOfJobsAcomplished/total * 100) + "% time pass " + (now - startingTime)); 
       lastLog = now; 
       numOfJobsAcomplished = 0; 
      } 
     } 

     protected abstract void doJob(); 
    } 

在doJob()方法,我在做刀片,我跑16工作的,16個線程(我發現,這是我的機器上性能最好)

無論如何,我的問題是關於結果,我得到85至105分鐘之間插入1,000,000行。這是否很快,或者我應該尋找不同的數據庫來處理?

P.S *當我將我也MD5Crypt算法散列

+1

'這是否快速'是主觀的。你的要求和/或限制是什麼?負載行爲在現實中會是什麼樣子?桌子上還有什麼其他的閱讀或寫作活動?此外,SQL查詢的格式也很重要。您是否使用參數化查詢來最小化網絡流量,解析和編譯時間等? – MatBailie 2012-01-13 15:49:34

+0

@Dems我只是使用「插入到用戶值('...');」 – 2012-01-13 15:57:48

+0

查看參數化查詢。如果您一次又一次地重複相同的查詢,他們通常執行得更快。 – MatBailie 2012-01-13 15:58:42

回答

1

我總是覺得很有趣,當有人試圖在軟件沒有考慮其他因素的考慮「怪」的寫入速度。那麼,我們開始吧。

MySQL有2個廣泛使用的引擎。 MyISAM和InnoDB。 InnoDB是一種事務性引擎,它使用集羣主鍵將記錄寫入硬盤。 這意味着它可以進行各種計算,以便安全地將數據寫入磁盤,並將順序記錄彼此相鄰地寫入。 這意味着使用主鍵查找速度很快,但需要一段時間才能寫下來。

要將其轉換爲純英文,這意味着您的計算機將稍微難以將數據物理寫入磁盤安全,並且可以快速找到記錄。

這也意味着在這整個考驗中的瓶頸是你的硬盤驅動器。 85分鐘插入1mil。記錄大約每秒插入200次。對於普通的7200RPM機械驅動器來說這是一個非常不錯的數字(我的驅動器可以達到350個IOPS)。因此,在350 IOPS(讓我們拿走我的驅動器)中,您達到了200,這是一個很棒的數字,可以看出您的硬盤用於讀取和寫入,並且您的操作系統可能需要多個需要HDD I/O的服務。

TL; DR - 如果您使用不同的軟件,寫入開始時可能會稍微快一點。在交換軟件之前,您需要考慮所有因素。

+0

我沒有說我在指責MySQL。我只是想明白這是一個好的速度與否。當我啓動我的服務器時,會有很多事情要運行。我只是想創造一個很好的性能飛機。 – 2012-01-13 16:13:12

+0

我試圖說明插入速度取決於硬件很多,特別是在HDD子系統上。基本上是的,對於機械7200轉硬盤它是一個好的速度。 – 2012-01-13 16:16:40

0

如果您想優化插入性能,我建議您將主鍵更改爲合成自動增量bigint。原因是Innodb在按鍵存儲鍵的主鍵上使用聚簇索引。如果使用非順序主鍵,則需要讀取內存塊,並在最差情況下爲每行寫回內存塊,而不是像使用順序鍵一樣使用高速緩存。當插入順序鍵時,性能會提高几個數量級,請嘗試一下。

CREATE TABLE `users` (
    `id` bigint(20) auto increment not null PRIMARY KEY, 
    `user_id` varchar(45) NOT NULL, 
    `full_name` varchar(45) NOT NULL, 
    `first_name` varchar(45) NOT NULL, 
    `last_nmae` varchar(45) NOT NULL, 
    `login` varchar(45) NOT NULL, 
    `password` varchar(45) NOT NULL, 
    UNIQUE KEY (`user_id`,`full_name`,`login`), 
    UNIQUE KEY `idusers_UNIQUE` (`user_id`), 
    UNIQUE KEY `login_UNIQUE` (`login`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$ 

順便說一句,我不知道什麼ID(USER_ID)是以前,所以我左邊在上,但如果用它作爲合成的主鍵,你可以取出來,如果你。

+0

好吧我運行一個測試,它看起來對性能沒有任何影響 – 2012-01-14 17:41:24

+0

您嘗試過多少行?你也想確保你的innodb_buffer_size設置正確,現在設置了什麼? – 2012-01-14 17:59:11

+0

什麼是innodb_buffer_size? – 2012-01-14 19:10:25