2017-05-02 18 views
0

不知道如何尋找這個,所以我很抱歉,如果這是之前問。隨着時間的推移翻轉記錄的狀態無迴歸

據說我提供了一組記錄。這些記錄具有某種狀態,即truefalse。隨着時間的推移,我們的客戶希望將文檔的特定子集從一個或另一個狀態切換。

所以當前記錄存儲在SQL數據庫(準確地說是PostgreSQL)。所以爲了保持狀態翻轉的歷史(並且爲了確保我們可以從頭開始重新運行所有的東西,萬一有些事情搞砸了),我們將所有更新語句存儲在版本控制的存儲庫中。但是,因爲這是SQL,並且一段時間後SQL變得非常複雜(爲了確保不迴歸,即以前請求爲false時未將狀態設置爲true)。

例如,我們在過去的翻轉記錄truefalse收到票#1和#2分別

-- DO THIS FOR TICKET #1 
UPDATE record 
SET  status = TRUE 
WHERE id IN (SELECT id 
       FROM records 
       WHERE this_criteria = 'that'); 


-- DO THIS FOR TICKET #2 
UPDATE record 
SET  status = FALSE 
WHERE id IN (SELECT id 
       FROM records 
       WHERE another_criteria = 'whatever') 

這是當我們有一票#3是在涉及的一個子集,我們做什麼在#1和#2的記錄

-- DO THIS FOR TICKET #3 
UPDATE records 
SET  statue = TRUE 
WHERE id IN (SELECT id 
       FROM records 
       WHERE true_criteria = 'something') 
     AND id NOT IN (-- regression ticket #1 
         SELECT id 
         FROM records 
         WHERE this_criteria = 'that' 
         UNION 
         -- regression ticket #2 
         SELECT id 
         FROM records 
         WHERE another_criteria = 'whatever'); 

所以我們現在正在做的是運行的#1的更新語句,再其次是#2,#最後3。正如所料,#3將永遠運行。我可以優化查詢,但從長遠來看它仍然不會起作用,因爲將來的票據將導致越來越複雜的條件被寫入,以避免覆蓋以前票證中設置的狀態。

既然我們正在尋找另一個項目的替代方案,並且我們期待未來地位的翻轉發生得更加頻繁。有什麼可能是一種更好的方式來管理這一點,並且如果可能的話,爲我們提供一種實際記錄更改的方式(不一定是SQL)?

我們不是逐批更新它們(想象一下,我們會定期將記錄逐個發送到管道中,並且客戶端的每個請求都是一個盒子,以便在適用的情況下翻轉記錄的狀態,最後這些記錄將被插入某些數據存儲)。所以我們將SQL替換成一些基於規則的迷你DSL,以確保在翻轉狀態之前滿足條件。但是,這看起來不像是對SQL方法的改進,因爲條件遲早會​​由於迴歸檢查而增長,並且規則實際上只是另一種格式的SQL。

的新門票#3的一個例子是這樣的

SET status TO TRUE 
CONDITION (is_equal, true_criteria, 'something') # new ticket #3 request 
      # REGRESSION in ticket #1 
      AND (not_equal, this_criteria, 'that') 
      # REGRESSION in ticket #2 
      AND (not_equal, another_criteria, 'whatever') 

一些事情正如你可以看到,而我沒有一次像SQL,語句把它做的所有記錄以上實際上只是原始SQL對應的變體。

編輯:

  1. 這不是關於SQL優化,我還可以實現這一點沒有使用關係型數據庫,然後我可以刪除標識符列。狀態變量不是由標識符的值決定的。
  2. 假設我要將收藏集放入Search Appliance,即ElasticSearch,所以如果我可以預先計算狀態會很好,所以我不必在用戶發出的查詢之上附加一個巨大的查詢DSL,以確保只返回status=true記錄。
  3. 我正在尋找替代解決方案,不必在關係數據庫中實施(因此我刪除了postgresql標籤)。
  4. 客戶端並不總是在乎他們的新請求是否會導致某些先前設置的狀態翻轉,他們只是希望確保以前翻轉的狀態在應用新條件時不會被隱式重寫。
  5. 在SQL實現中,我們犯了一個錯誤,就是沒有記錄狀態字段的更新日誌,而我們正在起草的那個將會有這種情況,所以是的,我們必須有一種方法來記錄狀態翻轉。
+1

是id字段獨特之處? –

+0

是的,但這並不重要,我並不是在尋找SQL優化,但更多的是關於其他人如何在Jeffrey04上做這個 – Jeffrey04

+0

的策略是的,它*確實很重要,因爲你的子查詢指的是完全相同的記錄爲更新語句的目標記錄。見@BennjoeMordeno的答案。另外:您的狀態實際上是多餘的,因爲它可以從其他列重新計算。 – joop

回答

0

測試此對您的樣本數據,但我認爲你可以簡化您的in條款,擺脫not in條款像下面

UPDATE records 
SET  statue = TRUE 
WHERE id IN (SELECT id 
      FROM records 
      WHERE true_criteria = 'something' 
      and this_criteria <> 'that' 
      and another_criteria <> 'whatever' 
      ) 
+0

不,我不是在尋找SQL的優化,因爲條件會隨着時間的推移而增長。還分隔'IN'和'NOT IN'實際上有助於使其可讀(IN =用於新請求,NOT IN =用於迴歸處理) – Jeffrey04

0

如果ID域是唯一的,你可以簡化您的查詢:

UPDATE records 
    SET STATUS = TRUE 
    WHERE 
    true_criteria = 'something' 
    and 
    this_criteria <> 'that' 
    and 
    another_criteria <> 'whatever' 

雖然我認爲你可能正在查看另一個子查詢表,那麼這是行不通的。

+0

不,我不尋找SQL的優化,因爲條件會增長時間。還分隔'IN'和'NOT IN'實際上有助於使它可讀(IN =用於新請求,NOT IN =用於迴歸處理) – Jeffrey04

0

還不清楚你在問什麼。如果您想要一種簡單的方法來排除其他票據的條件,您可以將它們鏈接起來,將它們放入this_column (not) IN(a,b,c)列表中。 (假設id是主鍵,您的記錄表)


-- DO THIS FOR TICKET #3 
UPDATE records 
SET  statue = True 
    -- No need to flip it if it is already True 
WHERE status <> True 
    -- New condition for ticket #3 
AND true_criteria IN ('something') 
    -- regression ticket #1 
AND this_criteria NOT IN('that') 
    -- regression ticket #2 
AND another_criteria NOT IN ('whatever') 
    ; 
+0

我在問什麼是實現這個的替代方法(不一定是關係數據庫,因此我不需要關於如何優化查詢的建議) – Jeffrey04

+0

實現了一些機制,可以更容易地寫入條件(不會覆蓋以前的狀態),並可以記錄每個狀態翻轉 – Jeffrey04

相關問題