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

Výkon MySQL VIEW pro tabulky v kombinaci s UNION ALL

Souhlasím se všemi body ve skvělé odpovědi Billa Karwina.

Otázka: Je běžnou praxí vytvořit pohled pro diskutovaný sjednocovací dotaz a použít jej v mých spojeních, podvýběrech atd.?

Odpověď: S MySQL je běžnější praxí vyhnout se použití příkazu "CREATE VIEW".

Otázka: Pokud jde o výkon - bude horší, stejný nebo lepší ve srovnání s pouhým vložením do spojení, podvýběrů atd?

Odpověď: Odkazování na objekt pohledu bude mít stejný výkon jako ekvivalentní vložený pohled.

(Vyhledání objektu zobrazení, kontrola oprávnění a nahrazení odkazu na zobrazení uloženým SQL může být trochu více práce v porovnání s odesláním příkazu, který je jen o malinko delší. rozdíly jsou nepatrné.)

Otázka: Existují v tomto případě nějaké nevýhody pohledu?

Odpověď: Největší nevýhodou je, jak MySQL zpracovává pohled, ať už je uložený nebo inline. MySQL vždy spustí dotaz zobrazení a zhmotní výsledky z tohoto dotazu jako dočasnou tabulku MyISAM. Ale není tam žádný rozdíl, zda je definice pohledu uložena, nebo zda je zahrnuta inline. (Ostatní RDBMS zpracovávají pohledy mnohem jinak než MySQL).

Jednou velkou nevýhodou pohledu je, že predikáty z vnějšího dotazu se NIKDY netlačí dolů do dotazu pohledu. Pokaždé, když odkazujete na tento pohled, dokonce i s dotazem na jednu hodnotu id, MySQL spustí dotaz pohledu a vytvoří dočasnou tabulku MyISAM (bez indexů) a POTOM MySQL spustí vnější dotaz proti tomuto dočasnému Tabulka MyISAM.

Pokud jde o výkon, myslete na odkaz na zobrazení na stejné úrovni jako „CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM " a "INSERT INTO t (cols) SELECT ... ".

."

MySQL ve skutečnosti odkazuje na inline pohled jako na "odvozenou tabulku" a tento název dává velký smysl, když rozumíme tomu, co s ním MySQL dělá.

Moje osobní preference je nepoužívat příkaz „CREATE VIEW“. Největší nevýhodou (jak to vidím já) je, že "skrývá" SQL, který se provádí. Pro budoucího čtenáře vypadá odkaz na pohled jako tabulka. A pak, když jde napsat příkaz SQL, bude odkazovat na pohled, jako by to byla tabulka, takže je to velmi pohodlné. Pak se rozhodne, že připojí ten stůl k sobě s dalším odkazem na něj. (Pro druhý odkaz, MySQL také spustí tento dotaz znovu a vytvoří další dočasnou (a neindexovanou) tabulku MyISAM. A nyní je na tom operace JOIN. A pak se přidá predikát "WHERE view.column ='foo'" na vnějším dotazu.

Nakonec to „skryje“ nejviditelnější zlepšení výkonu a vloží tento predikát do dotazu zobrazení.

A pak někdo přijde a rozhodne se, že vytvoří nový pohled, který odkazuje na starý pohled. Potřebuje pouze podmnožinu řádků a nemůže upravit stávající pohled, protože by to mohlo něco narušit, takže vytvoří nový pohled... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.

A nyní odkaz na myview nejprve spustí dotaz publicview, vytvoří dočasnou tabulku MyISAM, pak se proti tomu spustí dotaz myview, čímž se vytvoří další dočasná tabulka MyISAM, proti které bude spuštěn vnější dotaz.

V zásadě má pohodlí zobrazení potenciál pro neúmyslné problémy s výkonem. S definicí pohledu dostupnou v databázi pro kohokoli ji někdo použije, i když to není nejvhodnější řešení.

Přinejmenším s inline zobrazením si osoba, která píše příkaz SQL, více uvědomuje skutečný SQL, který se provádí, a mít všechny tyto SQL rozvržené dává příležitost vyladit jej pro výkon.

Moje dva centy.

TAMING BESTLY SQL

Zjistil jsem, že použití běžných pravidel formátování (které moje nástroje automaticky dělají) může změnit monstrózní SQL na něco, co mohu číst a s čím mohu pracovat.

SELECT row.col1
     , row.col2
     , person.*
  FROM some_table row
  LEFT
  JOIN ( SELECT 'person'  AS `person_type`
              , p.id      AS `id`
              , CONCAT(p.first_name,' ',p.surname) AS `name`
           FROM person p
          UNION ALL
         SELECT 'company' AS `person_type`
              , c.id      AS `id`
              , c.name    AS `name`
           FROM company c
       ) person
    ON person.id = row.person_id
   AND person.person_type = row.person_type

Stejně tak bych se pravděpodobně úplně vyhnul vloženému zobrazení a použil bych podmíněné výrazy v seznamu SELECT, i když je to pro mnoho sloupců nepraktické.

SELECT row.col1
     , row.col2
     , row.person_type AS ref_person_type
     , row.person_id   AS ref_person_id
     , CASE
       WHEN row.person_type = 'person'  THEN p.id 
       WHEN row.person_type = 'company' THEN c.id
       END AS `person_id`
     , CASE
       WHEN row.person_type = 'person'  THEN CONCAT(p.first_name,' ',p.surname)
       WHEN row.person_type = 'company' THEN c.name
       END AS `name`
  FROM some_table row
  LEFT
  JOIN person p
    ON row.person_type = 'person'
   AND p.id = row.person_id
  LEFT
  JOIN company c
    ON row.person_type = 'company'
   AND c.id = row.person_id


  1. Jak vynásobit dvě hodnoty sloupce a zobrazit jeho výsledek na konci každého řádku?

  2. Jak převést řetězec na Hex a naopak?

  3. mysql a indexy s více než jedním sloupcem

  4. GET_FORMAT() Příklady – MySQL