sql >> Databasteknik >  >> RDS >> Mysql

MySQL-prestanda för VIEW för tabeller kombinerat med UNION ALL

Jag instämmer i alla punkter i Bill Karwins utmärkta svar.

F: Är det normal praxis att skapa en vy för diskuterade fackliga frågor och använda den i mina anslutningar, underval etc?

Svar: Med MySQL är de mer normala metoderna att undvika att använda "CREATE VIEW"-satsen.

F: När det gäller prestanda - blir det sämre, lika eller bättre jämfört med att bara infoga det i joins, subselects etc?

Svar: Att referera till ett vyobjekt kommer att ha samma prestanda som en motsvarande inlinevy.

(Det kan vara lite mer arbete för att slå upp vyobjektet, kontrollera privilegier och sedan ersätta vyreferensen med den lagrade SQL-koden, jämfört med att skicka en sats som bara är en liten liten bit längre. Men någon av dessa skillnaderna är obetydliga.)

F: Finns det några nackdelar med att ha en syn i det här fallet?

Svar: Den största nackdelen är hur MySQL bearbetar en vy, oavsett om den är lagrad eller inline. MySQL kommer alltid att köra vyfrågan och materialisera resultaten från den frågan som en tillfällig MyISAM-tabell. Men det är ingen skillnad där om vydefinitionen är lagrad eller om den ingår inline. (Andra RDBMS bearbetar synpunkter mycket annorlunda än MySQL).

En stor nackdel med en vy är att predikat från den yttre frågan ALDRIG trycks ner i vyfrågan. Varje gång du refererar till den vyn, även med en fråga för ett enda id-värde, kommer MySQL att köra vyfrågan och skapa en tillfällig MyISAM-tabell (utan index på den), och DÅ kommer MySQL att köra den yttre frågan mot den tillfälliga MyISAM-tabell.

Så, i termer av prestanda, tänk på en referens till en vy i paritet med "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM " och "INSERT INTO t (cols) SELECT ... ".

MySQL hänvisar faktiskt till en inlinevy som en "härledd tabell", och det namnet är mycket vettigt när vi förstår vad MySQL gör med det.

Min personliga preferens är att inte använda "CREATE VIEW"-satsen. Den största nackdelen (som jag ser det) är att den "gömmer" SQL som körs. För den framtida läsaren ser hänvisningen till vyn ut som en tabell. Och sedan, när han går för att skriva en SQL-sats, kommer han att referera till vyn som om det vore en tabell, så väldigt bekvämt. Sedan bestämmer han sig för att han ska ansluta sig till det där bordet med en annan referens till det. (För den andra referensen kör MySQL också den frågan igen och skapar ytterligare en tillfällig (och oindexerad) MyISAM-tabell. Och nu finns det en JOIN-operation på det. Och sedan läggs ett predikat "WHERE view.column ='foo'" till på den yttre frågan.

Det slutar med att den "gömmer" den mest uppenbara prestandaförbättringen, genom att predikatet glider in i vyfrågan.

Och sedan kommer någon och bestämmer sig för att de ska skapa en ny vy, som refererar till den gamla vyen. Han behöver bara en delmängd av rader och kan inte ändra den befintliga vyn eftersom det kan bryta något, så han skapar en ny vy... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.

Och nu kommer en referens till myview först att köra publicview-frågan, skapa en temporär MyISAM-tabell, sedan körs myview-frågan mot den, skapa en annan temporär MyISAM-tabell, som den yttre frågan kommer att köras mot.

I grund och botten har bekvämligheten med utsikten potential för oavsiktliga prestationsproblem. Med vydefinitionen tillgänglig i databasen för alla att använda, kommer någon att använda den, även där det inte är den lämpligaste lösningen.

Åtminstone med en inline-vy är den person som skriver SQL-satsen mer medveten om den faktiska SQL som exekveras, och att ha allt som SQL lagt ut ger en möjlighet att justera den för prestanda.

Mina två cent.

TAMING BEASTLY SQL

Jag upptäcker att användning av vanliga formateringsregler (som mina verktyg automatiskt gör) kan böja monstruös SQL till något jag kan läsa och arbeta med.

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

Jag skulle vara lika sannolikt att undvika inline-vyn överhuvudtaget och använda villkorliga uttryck i SELECT-listan, även om detta blir mer otympligt för många kolumner.

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. Visa dropdown i HTML med PHP

  2. Mysql Rekursiv lagrad procedur...Gräns ​​0 uppnått...kan inte ändra variabeln max_sp_recursion_depth

  3. Platta tabellpivotstil för en Datagridview

  4. Lagrar en array av okänd längd