2012-10-21 80 views
1

這是我的設置:如何選擇一個表中的記錄,但不是多個PKID的記錄?

records包含多個(多於兩個)PKID列以及其他一些列。

cached_records只有兩列,它們與records中的兩個PKID相同。

例如,我們假設records具有PKID'keyA','keyB'和'keyC',而cached_records只有'keyA'和'keyB'。

我需要從records表中取出合適的PKID(如'keyA'和'keyB')不在cached_records表中的行。

如果我只有一個PKID的工作,我知道這個任務是多麼的簡單:

SELECT 
    pkid 
FROM 
    records 
WHERE 
    pkid NOT IN (SELECT pkid FROM cached_records) 

然而,事實上,在兩個PKIDs意味着我不能用一個簡單的NOT IN。這是我目前有:

SELECT 
    `keys`.`keyA` AS `keyA`, 
    `keys`.`keyB` AS `keyB` 
FROM 
    (
     SELECT DISTINCT 
      `keyA`, 
      `keyB` 
     FROM 
      `records` 
    ) AS `keys` 
     LEFT JOIN 
       `cached_records` AS `cached` 
      ON 
        `keys`.`keyA` = `cached`.`keyA` 
       AND 
        `keys`.`keyB` = `cached`.`keyB` 
WHERE 
    (
      `cached`.`keyA` IS NULL 
     AND 
      `cached`.`keyB` IS NULL 
    ) 

(該DISTINCT是必要的,因爲,因爲我只是從records表抓住兩個多PKIDs的,有可能是重複的,我真的不需要重複;「keyC '沒有被使用,它有助於確定記錄的唯一性)。上面的查詢工作得很好,但是,隨着cached_records表增長,查詢需要更長和更長的時間來處理(我們現在正在談論分鐘,有時需要足夠長的時間才能讓代碼掛起並崩潰)。

所以,我想知道什麼是最有效的方式來做這種操作(從一個表中選擇行不存在於另一個表中的行)與多個PKIDS而不是隻有一個...

回答

2

這應該是更快:

SELECT DISTINCT 
    `records`.`keyA` AS `keyA`, 
    `records`.`keyB` AS `keyB` 
FROM 
    `records` 
     LEFT JOIN 
       `cached_records` AS `cached` 
      ON 
        `records`.`keyA` = `cached`.`keyA` 
       AND 
        `records`.`keyB` = `cached`.`keyB` 
WHERE 
      `cached`.`keyA` IS NULL -- one is enough here 

注:

  • 與查詢的表,你失去了很多的性能。您可以在這裏選擇最外面的SELECT。
  • 就足夠了檢查兩個鍵中的一個,如果他們是空的,因爲沒有人可以爲空
  • 你應該確認keyAkeyB列屬於同一類型的,並沒有轉換髮生(在工作見過這樣的實時代碼...)
  • 您應該在表上有適當的索引。這個查詢的分鐘是一些可怕的事情的跡象...(或瘋狂的數據量)
+1

我實施了一些建議,但這是殺手:他們的鑰匙是不同的類型! (我認爲我已經修復了這個問題,但是在傾倒和恢復不同的數據庫轉儲時,我想我最終使用了一個沒有固定的轉儲...),所以我加入了一個pkids作爲整數的表,其他作爲varchars。 – jzimmerman2011

+0

爲什麼是殺手?無法例如'records.keyA = CAST(cached.keyA AS INTEGER)'解決這個問題? –

+0

@TerjeD它甚至不需要,MySQL爲你做。問題不在於**不能正常工作**,而是因爲它非常麻煩。 – ppeterka

相關問題