2014-03-04 41 views
0

一些背景觸發複雜的配置條件

我們有哪些可選集成到其他幾個系統的系統。我們的系統將數據從MySQL數據庫轉移到其他系統。不同的客戶需要傳輸不同的數據爲了不觸發這些外部系統不必要的傳輸(當沒有相關數據發生變化時),我們有一個「導出」表,其中包含任何客戶感興趣的所有信息以及運行SQL文件中定義的SQL查詢的服務導出表中的數據與其他表中的數據相匹配並更新導出表,我們並不滿足以下幾種原因的解決方案:

  • 沒有客戶使用超過這些列的一小部分,儘管每列至少有一個客戶使用。
  • 隨着數據庫的增長,該服務正在對系統造成越來越大的壓力。即使沒有客戶擁有特別大量的數據(所有相關表中大約15000行,最大值),某些服務器在該服務比較數據時會完全凍結,這可能需要2分鐘(!)。我們擔心如果我們得到一個擁有大量數據的客戶會發生什麼。通過創建一些索引和改進SQL查詢可以提高性能,但我們覺得這是從錯誤的方向攻擊問題。
  • 它不是很靈活,也不可擴展。每當客戶有興趣傳送其他客戶以前沒有感興趣的數據(這種情況很多)時,必須添加新的列,只是感覺... icky。我不知道它有多重要,但我們目前在這張表中最多有37列,而且還在不斷增長。

我們想要做的

取而代之的是什麼,我們希望有一個非常精簡下來的「出口」表中僅包含最低限度的信息,即表和行的主鍵已更新,此行應該導出到的系統以及一些時間戳。然後,每當更新配置爲保證更新的列時,每個相關表中的觸發器都會更新此導出表。這種配置應該從另一個表(其中,在將來某個時候,可以從我們的網頁圖形用戶界面來配置)來讀取,看起來像這樣:

+--------+--------+-----------+ 
| system | table | column | 
+--------+--------+-----------+ 
| 'sys1' | 'tbl1' | 'column1' | 
+--------+--------+-----------+ 
| 'sys2' | 'tbl1' | 'column2' | 
+--------+--------+-----------+ 

現在,TBL 1觸發將從此表中讀取時,行更新。上面的配置應該意味着如果tbl1中的column1發生了變化,那麼應該更新sys1的導出行,如果column2也已更改,那麼sys2的導出行也應該更新,等等。

到目前爲止,它似乎都可行,但當你不是SQL天才時有點棘手。然而,我們希望能夠定義一些更復雜的條件,至少像「column3 ='Apple'或column3 ='Banana'」,這是問題的核心......

所以,總結一下:

  • 什麼是允許以這種方式配置觸發器的最佳方式?
  • 我們瘋了嗎?觸發器是否是正確的方式,或者我們應該堅持我們的服務,抨擊某些索引並吸取它?還是有第三種選擇?
  • 我們期望看到多少性能提升? (這是否值得?)
+0

嗯,我剛剛發現動態SQL不允許在觸發器內......真是無賴。猜猜它已經回到了繪圖板。 – moggizx

+0

我們得出的結論是,最好的方法是從PHP生成靜態觸發器,而實際上這可能是更好的解決方案。 – moggizx

回答

0

這實際上是不可能的,因爲SQL中不支持動態SQL。因此我們想出了從PHP讀取配置表並生成「靜態」觸發器。我們將嘗試有2桌,一個爲列和一個條件,像這樣:

Columns 
+--------+--------+-----------+ 
| system | table | column | 
+--------+--------+-----------+ 
| 'sys1' | 'tbl1' | 'column1' | 
+--------+--------+-----------+ 
| 'sys2' | 'tbl1' | 'column2' | 
+--------+--------+-----------+ 

Conditions 
+--------+--------+-------------------------------------------+ 
| system | table |     condition    | 
+--------+--------+-------------------------------------------+ 
| 'sys1' | 'tbl1' | 'column3 = "Apple" OR column3 = "Banana"' | 
+--------+--------+-------------------------------------------+ 

然後,只需建立一個這樣的語句在PHP(僞代碼):

DROP TRIGGER IF EXISTS `tbl1_AUPD`; 

CREATE TRIGGER `tbl1_AUPD` AFTER UPDATE ON tbl1 FOR EACH ROW 
    BEGIN 
    IF (*sys1 columns changed*) AND (*sys1 condition1*) THEN 
     updateExportTable('sys1', 'tbl1', NEW.primary_key, NEW.timestamp); 
    END IF; 
    IF (*sys2 columns changed*) THEN 
     updateExportTable('sys2', 'tbl1', NEW.primary_key, NEW.timestamp); 
    END IF; 
END; 

這似乎對我們來說是最好的解決方案,甚至可能比我所要求的更好,但如果有人有更好的建議,我全都是耳朵!