有關於儲存過程的一個笑話

Joshua_q發表於2013-11-29

     我真的是上來講一個笑話的,這是個傳統笑話,需要慢慢講。

     我同事離職以後,統計平臺的所有程式碼就被我接過來了。這個統計平臺是用MySQL搭建的,5.1版本,伺服器是DELL的,有16個CPU和32G記憶體,700G的data空間,說真的這個配置對於我這種喜歡IOE的人來說實在是看不下去。

     接過這個系統後我發現有一個過程需要跑三個小時,從前4點開始跑,到早上9點前也就出來了,於是也就沒有什麼。可是後來因為生產伺服器壓力很大,ETL的 時間被推後了很多,導致我的過程只能7點開始跑,這樣子,加上資料入庫,這個系統的日報往往要11點甚至12點才能跑出來,領導問我為什麼沒有資料的時候 我真的不知道該如何狡辯。於是我想到了把計算過程遷移到Oracle上。我也這麼做了,效果很好,這個三小時過程Oracle只需要不到1分鐘然後 spool出來load data都比原來的過程快很多倍。於是我就安心的用起了Oracle。

     但是我今天工程師精神氾濫了,我想知道為什麼同樣是資料庫,人家阿里能把效能調校的那麼好,我們就要等那麼久?

     我跟蹤了一下,最慢的是這樣的一個SQL:

    

select distinct b.name from table_a a inner join table_b b on a.id = b.id group by b.name

     其中A表1億餘資料,B表2千萬左右,資料量可以說已經很大了。a的ID有一個索引,explain了以後這個SQL也走了索引,兩個表都走了。這就很奇 怪了,於是繼續看執行計劃,extra那裡有個temp table還有一個filesort。於是我開始想笑,這是誰啊,distinct了還要group by一下b.name?於是我檢視了一下b的表結構,這個表上的name是有一個索引的。我於是懂了從前的程式設計師為什麼要畫蛇添足的加一個group by。這在Oracle程式設計師看來是愚蠢的行為裡,其實蘊含了一個MySQL的小技巧。我接觸MySQL不長時間,但是通過讀各種書籍發現MySQL的索 引很有趣,尤其是聚集索引,整個InnoDB表就是一個索引。
      扯遠了,這個SQL裡,就是因為這個group by讓b表也走了索引,但是,當時的程式設計師應該是忘掉了去掉前面的distinct,於是導致了悲劇的發生。

      這個SQL完整版是這樣子的:

     

insert into table_c(day_id, name, flag) select '20131128', distinct b.name, 1 from table_a a inner join table_b b on a.id = b.id group by '20131128', b.name;

      去掉了distinct以後這個SQL還是很慢,半天插入不了。table_c有很多索引,這是個典型的DW表,很大。於是我建了一箇中間表,只有一個字 段name,可是我發現插入的速度還是很慢,非常慢,於是我想起了幾天前我看的《高效能MySQL》,裡面169頁還是179頁講過頁分裂的概念,提及了 一個小技巧,就是每個表都應該有一個自增的主鍵,這樣子插入速度會有一定的提升,於是我把mid表改了,有兩個欄位:id,name,其中id是自增的主 鍵。這樣一來,插入mid表只需要5min左右,而把mid表用簡單的select語句插入table_c只需要20s。是我想要的效率。

     我學習MySQL只有短短的幾個月時間,而且沒有時間從最基礎的開始學,都是需要什麼知識就趕緊去看《高效能MySQL》,這本書真不錯,當做一本救急用 的字典確實可以滿足作為一個開發人員的需要。當然了,我的定位是開發型DBA,這本書裡講管理入門的還比較少,我還是要好好學習。歡迎大家指正。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28207565/viewspace-1061702/,如需轉載,請註明出處,否則將追究法律責任。

相關文章