Views (MySQL)

Uit De Vliegende Brigade
Naar navigatie springen Naar zoeken springen

Views zijn virtuele tabellen. Een view wordt samengesteld als een select query, inclusief gebruik van joines. Je kunt views niet gebruiken om data weg te schrijven. Ik heb zelf nooit goed gebruik kunnen maken van views.

Waarom?

Enkele situaties waarin views voor mij handig kunnen zijn.

Abstractielaag voor tabellen

Een filter is een view met maar één tabel. In de tijd dat ik veel in Microsoft Access werkte, defineerde ik filters met de suffix _f. Ik had bv. tabel order_tbl en bijbehorend filter order_f. Vervolgens werkte ik nooit rechtstreeks op die tabel, maar altijd op het filter. Mocht de onderliggende tabel vervangen worden door een andere tabel of zoiets, dan had ik er op deze manier een abstractielaag tussenzitten.

Deze code uit Drupal is hier vermoedelijk een voorbeeld van:

create view semaphore as select * from mb7semaphore;

Of deze aanpak voor mij ooit van nut is geweest? Waarschijnlijk niet → Program today for today and tomorrow for tomorrow - Niet doen. Waarom het voor Drupal wellicht wel werkt, maar niet voor mij? Omdat Drupal door veel verschillende mensen wordt gebouwd, en er veel concurrency-issues zijn. Da's niet te vergelijken met mijn situatie.

Abstractielaag voor ingewikkelde select-queries

Een tijdje gebruikte ik een view in een datawarehouse om de prijzen uit verschillende tabellen samen te voegen en in een uniforme manier aan te bieden.

Eigenlijk nooit veel nut van gehad. Tegenwoordig wordt alle brondata door sprocs omgefietst tot tmp-tabellen waarmee ik werk, en om in specifieke gevallen met views te werken, creëert mogelijk meer verwarring dan orde.

Abstractielaag voor import-tabellen met lastige namen

Eén van de uitdagingen tav. datawarehousing is, om ondubbelzinnige single sources of truth (SSOD) [1] te hebben. De oplossing die ik sinds eind 2017 toepas: De importabellen zijn de SSOD's. Om deze als zodanig te identificeren, krijgen ze namen zoals 20180510_xml_price_imp. De eerste acht velden geven de datum aan. Daarna volgt een 'vrije omschrijving', in dit geval xml_price, gevolgd door de suffix _imp die aangeeft dat het om geïmporteerde SSOD-data gaat.

Ik ben erg blij met mezelf met deze mooie oplossing, maar er is één probleem: Tabelnamen zoals 20180510_xml_price_imp vind ik onwerkbaar. En hier heb ik een tijdje views voor gebruikt. Dus dat ik aan het begin van een project een view defineer op die tabel met een practische naam. In dit geval zou dat gewoon price kunnen zijn.

Nadelen

  • Views zijn in mijn beleving nogal losjes verbonden met de achterliggende databron. Goede kans dat ik na bv. een half jaar niet meer kan achterhalen op welke tabel de view price betrekking heeft
  • Ik werk rechtstreeks op de bron-data, ook al is het maar een view.

Oplossing

Voor projecten werk ik vrijwel altijd met sprocs die een brontabel omfietsen tot een tmp-tabel waar ik vervolgens mee aan de slag ga. Waarschijnlijk het beste om binnen dergelijke sprocs een tijdelijke oplossing te verzinnen voor dit naamgevingsprobleem. Hetzij met views, hetzij met tmp-tabellen. Ik vermoed dat ik dit laatste het prettigste vind, want ik werk al vaak op die manier.

Beperkingen

Niet goed bij te werken

Als je eenmaal een view hebt aangemaakt, en je wilt deze naderhand bijwerken, dan gaat dat niet lekker: De SQL-code wordt door MySQL in geparste vorm opgeslagen (oa. worden alle objectnamen binnen `backticks` geplaatst). Deze geparste code vind ik vervelend om mee te werken. Hier is geen directe oplossing voor [2].

Workarounds:

  • View aanmaken in SQL, dus in een gewoon script, of zelfs in een sproc - Is goed te doen. Zie het voorbeeld elders in dit artikel van de Drupal-view
  • De broncode van de view in een apart bestand bij te houden, of zelfs in een tekstveld in dezelfde database. Erg vrolijk word ik daar echter niet van.

Geen indices

Je kunt geen indices defineren op een view. Vermoedelijk werken indices op de oorspronkelijke tabel wél in bijbehorende views.

Verandert niet mee

[3]:

The view definition is “frozen” at creation time and is not affected by subsequent changes to the definitions of 
the underlying tables. For example, if a view is defined as SELECT * on a table, new columns added to the table 
later do not become part of the view, and columns dropped from the table will result in an error when selecting 
from the view. 

Dit vind ik altijd tricky, omdat de gevolgen vermoedelijk desastreus kunnen zijn.

Oplossing: Views steeds opnieuw defineren als je 'm gaat gebruiken. Net als wat ik doe met tmp-tabellen. Echter: Waarom dan nog views gebruiken?

Verstoort backups

Als een view defect is, kan er geen backup gemaakt worden van de betreffende database. Als je je daar niet van bewust bent of daar niet op controleert, kan het gebeuren dat je al tijden geen backup hebt gemaakt. Ik vermoed dat defecte views vrij gemakkelijk kunnen ontstaan, itt. defecte sprocs.

Bronnen