sql >> Databáze >  >> RDS >> Sqlserver

Aktualizujte, pokud se liší/změnily

Během kompilace a provádění dotazu SQL Server netrvá dlouho, aby zjistil, zda příkaz UPDATE skutečně změní nějaké hodnoty nebo ne. Prostě provádí zápisy podle očekávání, i když zbytečné.

Ve scénáři jako

update table1 set col1 = 'hello'

můžete si myslet, že SQL nic neudělá, ale bude – provede všechny potřebné zápisy, jako byste skutečně změnili hodnotu. K tomu dochází u fyzické tabulky (nebo seskupeného indexu) i všech indexů bez klastrů definovaných v tomto sloupci. To způsobí zápisy do fyzických tabulek/indexů, přepočítávání indexů a zápisy transakčního protokolu. Při práci s velkými datovými sadami přináší velké výhody v oblasti výkonu aktualizace pouze řádků, které dostanou změnu.

Pokud se chceme vyhnout režii těchto zápisů, když to není nutné, musíme vymyslet způsob, jak zkontrolovat potřebu aktualizace. Jedním ze způsobů, jak zkontrolovat potřebu aktualizace, by bylo přidat něco jako „where col <> 'hello'.

update table1 set col1 = 'hello' where col1 <> 'hello'

To by však v některých případech nefungovalo dobře, například pokud byste aktualizovali více sloupců v tabulce s mnoha řádky a hodnoty by se ve skutečnosti změnily pouze u malé podmnožiny těchto řádků. Je to z důvodu potřeby filtrovat všechny tyto sloupce a predikáty s nerovností obecně nemohou používat hledání indexu a režii zápisů do tabulek a indexů a záznamů transakčního protokolu, jak je uvedeno výše.

Existuje však mnohem lepší alternativa pomocí kombinace klauzule EXISTS s klauzulí EXCEPT. Cílem je porovnat hodnoty v cílovém řádku s hodnotami v odpovídajícím zdrojovém řádku a určit, zda je aktualizace skutečně potřeba. Podívejte se na upravený dotaz níže a prozkoumejte další filtr dotazů začínající na EXISTS. Všimněte si, že uvnitř klauzule EXISTS příkazy SELECT nemají klauzuli FROM. Tato část je zvláště důležitá, protože to pouze přidává další konstantní skenování a operaci filtru v plánu dotazů (cena obojího je triviální). Takže to, co skončíte, je velmi lehká metoda pro určení, zda je vůbec potřeba AKTUALIZACE, čímž se vyhnete zbytečné režii zápisu.

update table1 set col1 = 'hello'
/* AVOID NET ZERO CHANGES */
where exists 
    (
    /* DESTINATION */
    select table1.col1
    except
    /* SOURCE */
    select col1 = 'hello'
    )

Vypadá to příliš složitě oproti kontrole aktualizací v jednoduché klauzuli WHERE pro jednoduchou scénu v původní otázce, když aktualizujete jednu hodnotu pro všechny řádky v tabulce s doslovnou hodnotou. Tato technika však funguje velmi dobře, pokud aktualizujete více sloupců v tabulce a zdrojem vaší aktualizace je jiný dotaz a chcete minimalizovat zápisy a položky protokolů transakcí. Funguje také lépe než testování každého pole pomocí <>.

Úplnějším příkladem může být

update table1
   set col1 = 'hello',
       col2 = 'hello',
       col3 = 'hello'
/* Only update rows from CustomerId 100, 101, 102 & 103 */
where table1.CustomerId IN (100, 101, 102, 103)
/* AVOID NET ZERO CHANGES */
  and exists 
    (
    /* DESTINATION */
    select table1.col1
           table1.col2
           table1.col3
    except
    /* SOURCE */
    select z.col1,
           z.col2,
           z.col3
      from #anytemptableorsubquery z
     where z.CustomerId = table1.CustomerId
    )


  1. Unix SSH bez hesla

  2. Import JSON do Mysql

  3. mysql uložená procedura:parametr out

  4. Jak obnovit zálohu s jiným názvem