Hoi,

Ik heb een database met 8 verschillende variabelen. Van deze variabelen wil ik:
- Dag max/min
- Maand max/min
- jaar max/min
- Gister max/min

En bijbehorende datum en tijd.

Ik gebruik hiervoor de volgende query:
SELECT changed_on, $SensorNamen[$i] FROM sensorwaardes WHERE YEAR(`changed_on`)=$Year AND MONTH(`changed_on`) BETWEEN $Month AND $Month AND DAY(`changed_on`) BETWEEN $Day AND $Day ORDER BY ($SensorNamen[$i] IS NULL), $SensorNamen[$i]

Als ik maand nodig heb laat ik DAY weg en voor jaar laat ik DAY en MONTH weg.

Met dit soort query duurt het behoorlijk lang voordat ik alle gegevens heb.

Nu heb ik een andere query opbouw gevonden waar ik het ook mee voor elkaar heb, deze query ziet er als volgt uit:

SELECT MIN( temperatuur ) AS minRate, (
SELECT changed_on
FROM sensorwaardes
WHERE temperatuur = MIN( co.temperatuur )
AND day( changed_on ) = day( co.changed_on )
AND YEAR( changed_on ) = 2015
LIMIT 1
) AS min_date,

MAX( temperatuur ) AS maxRate, (
SELECT changed_on
FROM sensorwaardes
WHERE temperatuur = MAX( co.temperatuur )
AND day( changed_on ) = day( co.changed_on )
AND YEAR( changed_on ) = 2015
LIMIT 1
) AS max_date
FROM sensorwaardes co
WHERE YEAR( changed_on ) = 2015
GROUP BY YEAR(changed_on),day( changed_on )


In deze query staat nu maar 1 variabelen, maar op deze manier kan ik alle variabelen erin zetten en deze is veel sneller.

Ik ben nog vrij nieuw met MySQL en ik zie dat er veel tijdwinst te halen is in de opbouw van de query. Ik vraag me nu af kan het op een nog snellere manier en hoe werkt de laatste query?
Kun je de tabeldefinitie posten? Misschien kan een extra index of een ander kolomtype hier en daar nog de snelheid verbeteren.

Voor wat de performance betreft: als je een grote dataset hebt, kun je voor statistieken data aggregeren. Na 23:59:59 uur vanavond veranderen de minimum- en maximumtemperatuur van vandaag nooit meer. Voor vergelijkingen per week, maand, jaar en dergelijke kun je daarmee een tweede tabel maken die nog slechts twee metingen per dag bevat.

Met andere woorden: je kunt het aantal aggregate functions dat je op de complete dataset loslaat drastisch beperken als je de uitkomsten opslaat.
Ward van der Put op 11/03/2015 12:52:52

Kun je de tabeldefinitie posten? Misschien kan een extra index of een ander kolomtype hier en daar nog de snelheid verbeteren.

Voor wat de performance betreft: als je een grote dataset hebt, kun je voor statistieken data aggregeren. Na 23:59:59 uur vanavond veranderen de minimum- en maximumtemperatuur van vandaag nooit meer. Voor vergelijkingen per week, maand, jaar en dergelijke kun je daarmee een tweede tabel maken die nog slechts twee metingen per dag bevat.

Met andere woorden: je kunt het aantal aggregate functions dat je op de complete dataset loslaat drastisch beperken als je de uitkomsten opslaat.


Ik heb een tabel met 9 kolommen bestaande uit:
PID
changed_on
Sensor 1
Sensor 2
Sensor 3
Sensor 4
Sensor 5
Sensor 6
Sensor 7
Sensor 8

Daar heb ik ook aan zitten denken, om de waarden alvast uit te rekenen. Dan met een cron task elke keer de gegevens om 00:00:00 laten genereren. Nu zit er alleen nog maar data van deze maand in de database, waarschijnlijk neemt de zoektijd toe naar mate de database groeit..
Allereerst moet je een index zetten op changed_on.
Om deze te kunnen gebruiken moet je NOOIT functies over de kolom hebben in de where
Bijvoorbeeld:
.... WHERE YEAR(changed_on) = 2015

Kan je vervangen door:
.... WHERE changed_on >= CAST('2015-01-01' AS DATETIME)

Als je tabel in InnoDb staat is het zelfs beter om die AI primary key weg te halen en changed_on de PK te maken.
InnoDb tabellen hebben altijd één clustered index, en dat is de primary key tenzij je expliciet anders opgeeft. Aangezien je waarschijnlijk niets doet met dat niets zeggende nummertje en de invoer op oplopende tijden geschied is changed_on prima geschikt als PK.

Reageren