Ik ben het eens met alle punten in het uitstekende antwoord van Bill Karwin.
V: Is het normaal om een weergave te maken voor een besproken samenvoegquery en deze te gebruiken in mijn joins, subselecties, enz.?
A: Met MySQL is het gebruikelijker om het gebruik van de instructie "CREATE VIEW" te vermijden.
V: In termen van prestaties - zal het slechter, gelijk of beter zijn in vergelijking met het gewoon invoegen in joins, subselecties, enz.?
A: Verwijzen naar een view-object heeft dezelfde prestaties als een equivalente inline view.
(Er kan een heel klein beetje meer werk zijn om het view-object op te zoeken, privileges te controleren en vervolgens de view-referentie te vervangen door de opgeslagen SQL, in plaats van een instructie te verzenden die maar een heel klein beetje langer is. Maar elk van die verschillen zijn onbeduidend.)
V: Zijn er in dit geval nadelen aan het hebben van een uitzicht?
A: Het grootste nadeel is hoe MySQL een weergave verwerkt, of deze nu is opgeslagen of inline. MySQL zal altijd de view-query uitvoeren en de resultaten van die query materialiseren als een tijdelijke MyISAM-tabel. Maar er is geen verschil of de weergavedefinitie wordt opgeslagen of inline is opgenomen. (Andere RDBMS'en verwerken weergaven heel anders dan MySQL).
Een groot nadeel van een view is dat predikaten uit de buitenste query NOOIT naar beneden worden gepusht in de viewquery. Elke keer dat u naar die weergave verwijst, zelfs met een query voor een enkele id-waarde, voert MySQL de view-query uit en maakt een tijdelijke MyISAM-tabel (zonder indexen erop), en DAN zal MySQL de buitenste query uitvoeren tegen die tijdelijke MijnISAM-tabel.
Dus, in termen van prestaties, denk aan een verwijzing naar een weergave die vergelijkbaar is met "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM
" en "INSERT INTO t (cols) SELECT ...
".
MySQL verwijst eigenlijk naar een inline-weergave als een "afgeleide tabel", en die naam is heel logisch, als we begrijpen wat MySQL ermee doet.
Mijn persoonlijke voorkeur is om de instructie "CREATE VIEW" niet te gebruiken. Het grootste nadeel (zoals ik het zie) is dat het SQL die wordt uitgevoerd "verbergt". Voor de toekomstige lezer ziet de verwijzing naar de weergave eruit als een tabel. En als hij dan een SQL-instructie gaat schrijven, gaat hij naar de weergave verwijzen alsof het een tabel is, dus erg handig. Dan besluit hij dat hij die tafel bij zichzelf gaat voegen, met een andere verwijzing ernaar. (Voor de tweede referentie, MySQL voert die query ook opnieuw uit en maakt nog een andere tijdelijke (en niet-geïndexeerde) MyISAM-tabel. En nu is daar een JOIN-bewerking voor. En dan wordt een predikaat "WHERE view.column ='foo'" toegevoegd op de buitenste vraag.
Het "verbergt" uiteindelijk de meest voor de hand liggende prestatieverbetering en schuift dat predikaat in de view-query.
En dan komt er iemand langs en besluit dat ze een nieuwe weergave gaan maken, die verwijst naar de oude weergave. Hij heeft alleen een subset van rijen nodig en kan de bestaande weergave niet wijzigen omdat dat iets zou kunnen breken, dus maakt hij een nieuwe weergave... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.
En nu gaat een verwijzing naar myview eerst de publicview-query uitvoeren, een tijdelijke MyISAM-tabel maken, dan wordt de myview-query daartegen uitgevoerd, waardoor een andere tijdelijke MyISAM-tabel wordt gemaakt, waartegen de buitenste query wordt uitgevoerd.
Kortom, het gemak van de weergave heeft het potentieel voor onbedoelde prestatieproblemen. Met de weergavedefinitie die voor iedereen beschikbaar is in de database, zal iemand het gebruiken, zelfs als dit niet de meest geschikte oplossing is.
In ieder geval met een inline-weergave is de persoon die de SQL-instructie schrijft zich meer bewust van de daadwerkelijke SQL die wordt uitgevoerd, en als al die SQL is ingedeeld, kan deze worden aangepast voor prestaties.
Mijn twee cent.
BEESTELIJKE SQL TEAM
Ik merk dat het toepassen van reguliere opmaakregels (die mijn tools automatisch doen) monsterlijke SQL kan omzetten in iets dat ik kan lezen en waarmee ik kan werken.
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
Ik zou even waarschijnlijk de inline-weergave vermijden en voorwaardelijke expressies gebruiken in de SELECT-lijst, hoewel dit voor veel kolommen lastiger wordt.
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