[Discussie] Berekenen IN een database

Pagina: 1
Acties:

  • UltimateB
  • Registratie: April 2003
  • Niet online
Ik heb een query geschreven die een totaal van een winkelwagen berekend IN de database. Nu heb ik meningen gehoord van een aantal mensen en niet iedereen denkt er het zelfde over.

Er wordt geroepen dat het bijvoorbeeld slecht is om berekeningen uit te voeren in je database omdat je je business logic van de database laag moet scheiden. Een ander punt is dat het niet echt nuttig is om eigenlijk data uit je database te halen die je niet nodig hebt.

Wat is jullie visie hierop?

Illustratie:
SQL:
1
2
3
4
5
6
7
8
9
10
SELECT 
 SUM(
  CASE s_id  
   WHEN 1 THEN price*8 
   WHEN 5 THEN price*3 
  ELSE price 
  END 
 ) AS price 
FROM product_state 
WHERE s_id IN ( 1,5,6,8,10 )

"True skill is when luck becomes a habit"
SWIS


  • Cloud
  • Registratie: November 2001
  • Laatst online: 09-03 19:32

Cloud

FP ProMod

Ex-moderatie mobster

Waarschijnlijk is het verschil niet echt te merken, maar ook ik ben van mening, dat je de "logic" van je "opslag" moet scheiden. Want anders krijg je óveral berekeningen, in je code, in je queries. Dat maakt het geheel onduidelijker dan wanneer al je berekeningen op 1 plek staan, en al je queries alleen maar data ophalen.

Plus mochten je berekeningen later nog eens aangepast moeten worden, is dat in code makkelijker te doen dan al je queries nalopen. In je code zou je bijvoorbeeld variabelen bij kunnen houden die je vermenigvuldigingsfactor zijn.

Natuurlijk zijn simpele SUM() en COUNT() berekeningen hartstikke goed, maar veel verder dan dat zou ik persoonlijk niet gaan :) Ik denk eigenlijk dat het op smaak/gevoel aan komt. Maar in mijn ogen hoort een DB gewoon dingen op te slaan, dingen op te leveren, en dingen te wijzigen :)

Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana


  • BCC
  • Registratie: Juli 2000
  • Laatst online: 19:33

BCC

Als het een stored procedure is, kan ik het nog begrijpen. Anders zou ik het zeker niet doen, wat als bijvoorbeeld de BTW veranderd? Dan moet je AL je queries aanpassen...

Na betaling van een licentievergoeding van €1.000 verkrijgen bedrijven het recht om deze post te gebruiken voor het trainen van artificiële intelligentiesystemen.


  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Ik heb vandaag op het werk de perfecte reden gehoord om het in een query te doen. Het is een applicatie in Java en werkt met Hibernate als ORM.

Het probleem was dat bij een bepaald overzicht bepaalde onderdelen heel ver in elkaar genest zaten. Een heel aantal lussen diep. Hierdoor liep het geheugen (4GB) vol en crashte de applicatie op den duur. De oplossing hiervoor is om te zorgen dat deze lussen niet nodig zijn door de data bij voorbaat goed aan te leveren. Dus geen lijst met medewerkers, dan per medewerker een query draaien voor een percentage ofzo, etc., maar gewoon alle counts en gemiddeldes in de query berekenen.

Dit levert een flinke performancewinst op en de applicatie crasht niet meer. En het is sneller te maken dan in Java alle code te herschrijven.

Dit is overigens een specifiek geval, normaal wil ik ook niet te veel berekeningen en zo in een query.

@TS: Met CASE WHEN werken, beschouw ik overigens als nog lelijker. In gewone code probeer ik het te vermijden, maar in SQL helemaal, want dat wordt bij een beetje query compleet onoverzichtelijk. (En als die hard Java fan kan ik daar totaal niet tegen :) )
Mocht een case when onvoorkomelijk zijn, dan zet ik hem nog het liefst in een stored proc zodat ik hem (niet zie en) kan hergebruiken, want meestal zijn die cases vrij algemeen.

Fat Pizza's pizza, they are big and they are cheezy


Verwijderd

Ik zou dit niet in de database doen tenzij er echt bijzondere redenen zijn om het wel te doen. Dat heeft in ieder geval 2 redenen:
1) Scheiding van opslag en logica: zoals al eerder genoemd is het over het algemeen eenvoudiger om dergelijke zaken in code te berekenen (en aan te passen naar behoefte), en vaak kan dat ook behoorlijk efficient.

2) Schaalbaarheid: vaak is de logica van een applicatie in een goede ontwikkelomgeving makkelijk te verdelen over meerdere applicatieservers als de load te hoog wordt. Een database splitsen over verschillende servers is echter niet zo makkelijk, en daarom is het vaak het beste om de database niet meer dan noodzakelijk te belasten als je een schaalbaar systeem wil bouwen.

  • BertS
  • Registratie: September 2004
  • Laatst online: 13-02 08:33
Als je gebruik maakt van een goede O/R-mapper, kun je het mooie van beide werelden combineren. Ik werk zelf bijvoorbeeld met LLBLGen Pro. Daarbij heb je de querydefinitie (berekeningen, expressies, etc) in je code gedefinieerd, wat door de mapper wordt omgezet naar SQL.
Kortom: de logica in je code en de performance van je database :)

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

BCC schreef op donderdag 02 maart 2006 @ 19:40:
Als het een stored procedure is, kan ik het nog begrijpen. Anders zou ik het zeker niet doen, wat als bijvoorbeeld de BTW veranderd? Dan moet je AL je queries aanpassen...
Je kunt natuurlijk ook je queries (waar nodig) dynamisch opbouwen, zodat problemen met "semi-vaste variabelen" niet leiden tot het herschrijven van queries op tig plekken in je code. Dezelfde manier die je sowieso in je code dus al toe past.
Verwijderd schreef op donderdag 02 maart 2006 @ 21:18:
Ik zou dit niet in de database doen tenzij er echt bijzondere redenen zijn om het wel te doen. Dat heeft in ieder geval 2 redenen:
Ik zou dit juist wel in de database doen, magoed ik heb dan ook meer ervaring met relatief lichte, short-lived applicaties en weinig met zware of long-lived applicaties. De kans dat het daar anders is, is natuurlijk wel aanwezig.
1) Scheiding van opslag en logica: zoals al eerder genoemd is het over het algemeen eenvoudiger om dergelijke zaken in code te berekenen (en aan te passen naar behoefte), en vaak kan dat ook behoorlijk efficient.
De query definieer je bij je code (in de buurt), dus de opslag en logica zijn nog steeds gescheiden en imho is de query net zo makkelijk aan te passen als de code zelf. De plek waar de logica uitgevoerd wordt is natuurlijk wel verspreid.
2) Schaalbaarheid: vaak is de logica van een applicatie in een goede ontwikkelomgeving makkelijk te verdelen over meerdere applicatieservers als de load te hoog wordt. Een database splitsen over verschillende servers is echter niet zo makkelijk, en daarom is het vaak het beste om de database niet meer dan noodzakelijk te belasten als je een schaalbaar systeem wil bouwen.
Ik gok dat het schaalbaarder is om het (triviale, maar reeele) voorbeeldje in de TS wel in de database al te berekenen, daarmee bespaar je namelijk een enorme roundtrip van het omzetten van een hele lijst records naar een serie resultsets, die bij aankomst weer omgezet naar variabelen in de client-omgeving moeten worden en daar pas allemaal beoordeeld worden.
De database moet marginaal meer werk doen om dit resultset zelf te aggregeren tov het kaal doorsturen van de records, terwijl het resultset dusdanig groter kan zijn dat die kleine aggregatie-overhead in het niet valt bij de winst van de veel kleinere resultset.

Overigens ben ik het wel degelijk eens met je verhaal, maar interpreteer ik het een stuk ruimer: De database is imho bedoelt voor het opslaan van data, het kunnen wijzigen en verwijderen van die data en het op maat gemaakt terughalen van (samenvattingen) van die data.

[ Voor 5% gewijzigd door ACM op 02-03-2006 22:35 ]


  • DJ Buzzz
  • Registratie: December 2000
  • Laatst online: 15:26
Wat ik vaak merk is dat er niet veel situaties zijn waarbij dit direct van toepassing, zeker niet bij een winkelwagen zoals de TS noemt. Ik kan me namelijk moeilijk een winkelwagen voorstellen waarbij je alleen een prijs ziet een geen inhoud. En ik zie dan weer het nut niet van bedragen uitrekenen in je database terwijl je toch al de hele data in je winkelwagen weergeeft.

Wat anders is denk ik als je direct b.v. statistische data uit je gegevens wilt halen, het lijkt me dan juist wel handig om zo veel mogelijk hiervan in de database te doen. Die heeft per slot van rekening niet voor niks zaken als query optimizers. Je wilt niet zelf moeten nadenken over hoe je het stap voor stap het meest efficient de gegevens uit kunt rekenen (let wel dat ik het hier over moeten heb, als je het wilt kun je het natuurlijk nog steeds wel zelf doen :))

  • zneek
  • Registratie: Augustus 2001
  • Laatst online: 08-02-2025
Ik denk dat het gericht ophalen van data geen problemen hoeft te geven. Maar pas idd op met het uitvoeren van inhoudelijke berekeningen. Het preventief uitvoeren van een telling in een query kan erg interessant zijn. Maar meer dan dat moet je ook niet gaan doen, dan sluipt er businesslogic je database/queries in. En dan moet je zometeen op meerdere punten wijzigingen gaan aanbrengen, met als groot risico dat je dingen over het hoofd ziet, en er opeens "ongewenste" bijverschijnselen optreden (bugs ;) )

Ik zou trouwens ook nooit beginnen om op deze manier te denken. Performance komt later wel (behoudens natuurlijk een efficiente basisopzet). Veel performance problemen zijn ook (goedkoop) op te lossen door betere/snellere hardware (prik er 4Gb bij) of door bijv clustering. Daar wegen de extra kosten van development werk niet tegen op. Uitzonderingen daargelaten, en uiteraard is niet elke situatie zo zwart/wit.

  • UltimateB
  • Registratie: April 2003
  • Niet online
Zoals eerder al genoemd denk ik dat als de berekeningen dynamisch aangemaakt worden door het script het niet zo een probleem is om het te onderhouden. Het enige waar tegenaan gelopen kan worden is dat bij een migratie naar een andere database het mogelijk problemen op kan leveren als je database specifieke functies gebruikt voor berekenen.

Dan zal er dus niet alleen wat aangepast moeten worden aan de queries maar zal er daadwerkelijke code moeten worden aangepast.

Wat ACM dus eigenlijk zegt eigenlijk zie ik nu... :)
@TS: Met CASE WHEN werken, beschouw ik overigens als nog lelijker. In gewone code probeer ik het te vermijden, maar in SQL helemaal, want dat wordt bij een beetje query compleet onoverzichtelijk. (En als die hard Java fan kan ik daar totaal niet tegen :) )
Mocht een case when onvoorkomelijk zijn, dan zet ik hem nog het liefst in een stored proc zodat ik hem (niet zie en) kan hergebruiken, want meestal zijn die cases vrij algemeen.
Ik kan me voorstellen dat in SQL case wellicht wat ehrm, vreemd is. Maar waarom geen case gebruiken in je code? Ik zie dit juist als een valide methode om te zorgen dan de mogelijke uitkomsten beperkt worden tot hetgeen dat jij wilt, zeker als het gaat om gebruikers invoer.

@djbuzzzz:
Kijk eens op bijvoorbeeld de volgende link, linksboven. Het is in mijn ogen juist goed om een mooi overzicht van je winkelwagen te hebben op de voorpagina in teegenstelling tot bijvoorbeeld een hele waslijst met artikelen die de halve layout vernaaien. Maar dit is lichtelijk offtopic.

"True skill is when luck becomes a habit"
SWIS


Verwijderd

Nou als nog iemand anders je code nog moet kunnen lezen, graag alle logica op een plaats... is niet handig om overal SQL magic te hebben, dus ik ga voor alle logica op applicatie niveau... Echt bij mij is een DB niet meer dan een kaarten bak met foreigh keys

  • whoami
  • Registratie: December 2000
  • Laatst online: 07-04 22:26
Tja, je moet de voors en tegens afwegen...

'Echte' Business Logic in je database (dmv UDF's of SP's), zou ik ook niet doen. Echter, het ophalen van bepaalde samenvattingen (overzichten), zou ik wel dmv de databank doen. Je business logic laag kan dan die 'samenvattingen' gebruiken om beslissingen te nemen, of om de 'echte' business logic uit te voeren.

Hier beschrijf ik een ongeveer gelijkaardige situatie.

https://fgheysels.github.io/

Pagina: 1