sql >> Database teknologi >  >> RDS >> Mysql

MySQL ydeevne af VIEW til tabeller kombineret med UNION ALL

Jeg er enig i alle punkterne i Bill Karwins fremragende svar.

Sp: Er det normal praksis at oprette en visning til diskuteret fagforeningsforespørgsel og bruge den i mine joins, subselects osv.?

A: Med MySQL er den mere normale praksis at undgå at bruge "CREATE VIEW"-sætning.

Sp: Med hensyn til ydeevne - vil det være værre, ens eller bedre sammenlignet med blot at indsætte det i joins, subselects osv.?

A: Henvisning til et visningsobjekt vil have den samme ydeevne som en tilsvarende indlejret visning.

(Der kan være en lille bitte smule mere arbejde at slå visningsobjektet op, kontrollere privilegier og derefter erstatte visningsreferencen med den lagrede SQL, i forhold til at sende en sætning, der bare er en lille bitte smule længere. Men nogen af ​​disse forskelle er ubetydelige.)

Sp: Er der nogen ulemper ved at have et synspunkt i denne sag?

A: Den største ulempe er, hvordan MySQL behandler en visning, uanset om den er gemt eller inline. MySQL vil altid køre visningsforespørgslen og materialisere resultaterne fra den forespørgsel som en midlertidig MyISAM-tabel. Men der er ingen forskel, om visningsdefinitionen er gemt, eller om den er inkluderet inline. (Andre RDBMS'er behandler synspunkter meget anderledes end MySQL).

En stor ulempe ved en visning er, at prædikater fra den ydre forespørgsel ALDRIG bliver skubbet ned i visningsforespørgslen. Hver gang du refererer til den visning, selv med en forespørgsel efter en enkelt id-værdi, vil MySQL køre visningsforespørgslen og oprette en midlertidig MyISAM-tabel (uden indekser på den), og SÅ vil MySQL køre den ydre forespørgsel mod den midlertidige MyISAM-tabel.

Så med hensyn til ydeevne, tænk på en reference til en visning på linje med "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM " og "INSERT INTO t (cols) SELECT ... ".

MySQL refererer faktisk til en inline-visning som en "afledt tabel", og det navn giver meget mening, når vi forstår, hvad MySQL gør med det.

Min personlige præference er ikke at bruge "CREATE VIEW"-erklæringen. Den største ulempe (som jeg ser det) er, at den "skjuler" SQL, der bliver udført. For den fremtidige læser ligner henvisningen til visningen en tabel. Og så, når han går for at skrive en SQL-sætning, vil han referere til visningen, som om det var en tabel, så meget praktisk. Så beslutter han sig for, at han vil slutte sig til det bord for sig selv med en anden henvisning til det. (Til den anden reference kører MySQL også den forespørgsel igen og opretter endnu en midlertidig (og uindekseret) MyISAM-tabel. Og nu er der en JOIN-operation på det. Og så tilføjes et prædikat "WHERE view.column ='foo'" på den ydre forespørgsel.

Det ender med at "skjule" den mest åbenlyse ydeevneforbedring ved at glide prædikatet ind i visningsforespørgslen.

Og så kommer der nogen og beslutter sig for, at de vil skabe en ny visning, som refererer til den gamle visning. Han har kun brug for et undersæt af rækker og kan ikke ændre den eksisterende visning, fordi det kan ødelægge noget, så han opretter en ny visning... CREATE VIEW myview FRA publicview p WHERE p.col ='foo'.

Og nu vil en reference til myview først køre publicview-forespørgslen, oprette en midlertidig MyISAM-tabel, derefter køres myview-forespørgslen mod den, hvilket skaber en anden midlertidig MyISAM-tabel, som den ydre forespørgsel vil køre imod.

Grundlæggende har visningens bekvemmelighed potentiale for utilsigtede præstationsproblemer. Med visningsdefinitionen tilgængelig i databasen, som alle kan bruge, vil nogen bruge den, selv hvor det ikke er den mest passende løsning.

I det mindste med en indlejret visning er den person, der skriver SQL-sætningen, mere bevidst om den faktiske SQL, der udføres, og at have alt det SQL lagt ud giver mulighed for at justere det med henblik på ydeevne.

Mine to øre.

TAMING BEASTLY SQL

Jeg oplever, at anvendelse af almindelige formateringsregler (som mine værktøjer automatisk gør) kan bøje uhyrlig SQL til noget, jeg kan læse og arbejde 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

Det er lige så sandsynligt, at jeg overhovedet undgår den inline-visning og bruger betingede udtryk i SELECT-listen, selvom dette bliver mere uhåndterligt for mange kolonner.

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. Samtidige MySQL-indsættelser i samme tabel:hvordan?

  2. Er PostgreSQL-funktioner transaktionelle?

  3. MySQL dumpe i CSV-tekstfiler med kolonnenavne øverst?

  4. InnoDB:Kan ikke låse ./ibdata1 fejl:35