sql >> Databáze >  >> RDS >> Mysql

SQL UNION ALL k odstranění duplicit

Ale v příkladu má první dotaz podmínku ve sloupci a , zatímco druhý dotaz má podmínku ve sloupci b . Pravděpodobně to pochází z dotazu, který je obtížné optimalizovat:

SELECT * FROM mytable WHERE a=X OR b=Y

Tento dotaz je obtížné optimalizovat pomocí jednoduchého indexování B-stromu. Vyhledává vyhledávač index ve sloupci a ? Nebo ve sloupci b ? Ať tak či onak, hledání druhého termínu vyžaduje skenování tabulky.

Proto je trik použití UNION k rozdělení do dvou dotazů pro každý jeden termín. Každý dílčí dotaz může použít nejlepší index pro každý hledaný výraz. Poté výsledky spojte pomocí UNION.

Tyto dvě podmnožiny se však mohou překrývat, protože některé řádky mají b=Y může mít také a=X v takovém případě se takové řádky vyskytují v obou podmnožinách. Proto musíte provést duplicitní eliminaci, jinak uvidíte některé řádky dvakrát v konečném výsledku.

SELECT * FROM mytable WHERE a=X 
UNION DISTINCT
SELECT * FROM mytable WHERE b=Y

UNION DISTINCT je drahé, protože typické implementace třídí řádky, aby našly duplikáty. Stejně jako když použijete SELECT DISTINCT ... .

Také máme dojem, že je to ještě více „zbytečných“ prací, pokud dvě podmnožiny řádků, které sjednocujete, mají mnoho řádků vyskytujících se v obou podmnožinách. Je potřeba odstranit spoustu řádků.

Není však nutné odstraňovat duplikáty, pokud můžete zaručit, že dvě sady řádků jsou již odlišné. To znamená, že pokud zaručíte, že nedojde k žádnému překrývání. Pokud se na to můžete spolehnout, pak by bylo vždy zbytečné eliminovat duplikáty, a proto může dotaz tento krok přeskočit, a tudíž přeskočit nákladné třídění.

Pokud změníte dotazy tak, aby bylo zaručeno, že vyberou nepřekrývající se podmnožiny řádků, je to výhra.

SELECT * FROM mytable WHERE a=X 
UNION ALL 
SELECT * FROM mytable WHERE b=Y AND a!=X

Tyto dvě sady se zaručeně nebudou překrývat. Pokud má první sada řádky, kde a=X a druhá sada má řádky, kde a!=X pak nemůže existovat žádný řádek, který je v obou sadách.

Druhý dotaz tedy zachytí jen některé z řádků, kde b=Y , ale libovolný řádek, kde a=X AND b=Y je již součástí první sady.

Dotaz tedy dosáhne optimalizovaného vyhledávání dvou OR podmínky bez vytváření duplikátů a nevyžadující UNION DISTINCT operace.



  1. Jak REPEAT() funguje v MariaDB

  2. Spojte dva mysql dotazy do jednoho

  3. Spring's Stored Procedure - výsledky vracející se z procedury vždy prázdné

  4. Požadavek na legitimní příklad volání uložené procedury C#:MYSQL