Drastically optimise the queries behind fetch-data and device-data.

This commit is contained in:
Starbeamrainbowlabs 2019-06-22 21:08:12 +01:00
parent b4ae0b457b
commit 913786ec0b
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
7 changed files with 50 additions and 7 deletions

View file

@ -5,6 +5,10 @@ This is the changelog for the air quality web interface and its associated HTTP
- `[Code]` refers to internal changes to the code that have no direct impact on the web interface or the HTTP API, but are significant enough to warrant note. - `[Code]` refers to internal changes to the code that have no direct impact on the web interface or the HTTP API, but are significant enough to warrant note.
- `[Docs]` refers to changes to the [documentation](https://aq.connectedhumber.org/__nightdocs/00-Welcome.html). - `[Docs]` refers to changes to the [documentation](https://aq.connectedhumber.org/__nightdocs/00-Welcome.html).
## v0.11.1 - 22nd June 2019
- Drastically improve the performance of the backend SQL queries that power the heatmap and device graphs by over 35x!
- For users of the HTTP API, said queries are `fetch-data` and `device-data`.
## v0.11 - 21st June 2019 ## v0.11 - 21st June 2019
- [API] Add new [`list-devices-near`](https://aq.connectedhumber.org/__nightdocs/05-API-Docs.html#list-devices-near) action. - [API] Add new [`list-devices-near`](https://aq.connectedhumber.org/__nightdocs/05-API-Docs.html#list-devices-near) action.
- [API] Clarified that clients MUST ignore properties returned by the API that they do not understand. - [API] Clarified that clients MUST ignore properties returned by the API that they do not understand.

View file

@ -4,6 +4,12 @@ namespace SBRL;
class Generators { class Generators {
/**
* Generates a cryptographically secure random id, as a hex value.
* FUTURE: Improve this to return a safe base64 to reduce length.
* @param int $length The desired length of id.
* @return string The generated id.
*/
public static function crypto_secure_id(int $length = 64) { // 64 = 32 public static function crypto_secure_id(int $length = 64) { // 64 = 32
$length = ($length < 4) ? 4 : $length; $length = ($length < 4) ? 4 : $length;
return bin2hex(random_bytes(($length-($length%2))/2)); return bin2hex(random_bytes(($length-($length%2))/2));

View file

@ -7,11 +7,20 @@ namespace AirQuality;
*/ */
class ApiResponseSender class ApiResponseSender
{ {
/**
* Creates a new ApiResponseSender.
*/
function __construct() { function __construct() {
} }
/**
* Sends a plain-text error message.
* @param int $code The HTTP status code to send.
* @param string $message The plain-text message to send.
* @param array $extra_headers Any extra headers to return, in the format [["header", "value"], ["header", "value"], .....]
* @return void
*/
public function send_error_plain($code, $message, $extra_headers = []) { public function send_error_plain($code, $message, $extra_headers = []) {
http_response_code($code); http_response_code($code);
header("content-type: text/plain"); header("content-type: text/plain");

21
logic/Constants.php Normal file
View file

@ -0,0 +1,21 @@
<?php
namespace AirQuality;
/**
* Holds various constant value.
*/
class Constants
{
/**
* The DateTime->format() string for passing DateTimes to MariaDB.
* Note that if you don't use thsi format and use the ISO standard instead, it will silently complain at you, taking absolutely _ages_ over doing so.
* @var string
*/
const DATETIME_FORMAT_SQL = "Y-m-d H:i:s";
/**
* You should never instantiate an instance of this class!
*/
private function __construct() { }
}

View file

@ -56,8 +56,10 @@ class Database
// Replace tabs with spaces for debugging purposes // Replace tabs with spaces for debugging purposes
$sql = str_replace("\t", " ", $sql); $sql = str_replace("\t", " ", $sql);
if($this->settings->get("env.mode") == "development") if($this->settings->get("env.mode") == "development") {
// error_log("[Database/SQL]" . var_export($variables, true));
error_log("[Database/SQL] $sql"); error_log("[Database/SQL] $sql");
}
// FUTURE: Optionally cache prepared statements? // FUTURE: Optionally cache prepared statements?
$statement = $this->connection->prepare($sql); $statement = $this->connection->prepare($sql);

View file

@ -2,6 +2,7 @@
namespace AirQuality\Repositories; namespace AirQuality\Repositories;
use \AirQuality\Constants;
use \AirQuality\Database; use \AirQuality\Database;
use \SBRL\TomlConfig; use \SBRL\TomlConfig;
@ -97,8 +98,8 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
", [ ", [
"reading_type" => $type_id, "reading_type" => $type_id,
// The database likes strings, not PHP DateTime() instances // The database likes strings, not PHP DateTime() instances
"start_datetime" => $start_datetime->format(\DateTime::ISO8601), "start_datetime" => $start_datetime->format(Constants::DATETIME_FORMAT_SQL),
"end_datetime" => $end_datetime->format(\DateTime::ISO8601), "end_datetime" => $end_datetime->format(Constants::DATETIME_FORMAT_SQL),
] ]
)->fetchAll(); )->fetchAll();
} }
@ -138,8 +139,8 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
GROUP BY CEIL(UNIX_TIMESTAMP({$s("table_name_metadata")}.{$s("column_metadata_datetime")}) / :average_seconds);", [ GROUP BY CEIL(UNIX_TIMESTAMP({$s("table_name_metadata")}.{$s("column_metadata_datetime")}) / :average_seconds);", [
"device_id" => $device_id, "device_id" => $device_id,
"reading_type" => $type_id, "reading_type" => $type_id,
"start_datetime" => $start->format(\DateTime::ISO8601), "start_datetime" => $start->format(Constants::DATETIME_FORMAT_SQL),
"end_datetime" => $end->format(\DateTime::ISO8601), "end_datetime" => $end->format(Constants::DATETIME_FORMAT_SQL),
"average_seconds" => $average_seconds "average_seconds" => $average_seconds
] ]
)->fetchAll(); )->fetchAll();

View file

@ -1 +1 @@
v0.11 v0.11.1