Hello,
aujourd’hui, je stocke des points (longitude, latitude) avec un timestamp, sessionID et une mapID.
J'ai 2 types de requête :
Une qui récupère dans un intervalle de temps un nombre de session différentes par petits intervalles de temps.
Ca va me produire un graph temporel ensuite coté front-end.
Une autre requête qui récupère des ensembles de points (aggrégés par environ 1 mètre) dans un intervalle de temps, et groupé aussi par intervalle de temps.
Ceci est ensuite affiché sur une carte.
En gros, je vais vous mettre les requêtes :
Ici, on a un groupement d'environ 1 mètre pour les lat/lng, et 1 minute pour le temps.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 SELECT ROUND(p.lon * 100000) AS lon_int, ROUND(p.lat * 100000) AS lat_int, ROUND(UNIX_TIMESTAMP(p.timestamp)/60) AS ts_minute, COUNT(*) AS position_nb FROM `map_sessions` ms JOIN positions p ON (ms.id=p.`map_session_id` ) WHERE ms.map_id IN (57) AND p.timestamp BETWEEN '2019-08-31 12:00:00' AND '2019-09-02 12:00:00' GROUP BY ts_interval, lon_int, lat_int ORDER BY ts_interval
Mais pour le temps, cela peut varier en fonction de l'intervalle considéré. Exemple, sur1 jour, on aura un intervalle de 24*60*60 / 100 = 864.
Voici l'autre type de requête qu'on peut avoir :
En gros, c'est un peu pareil, mais on compte les sessions différentes et on prend toutes les positions possibles.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 SELECT ROUND(UNIX_TIMESTAMP(p.timestamp) / 60) AS ts_interval, COUNT(DISTINCT ms.id) AS session_nb, SUM(UNIX_TIMESTAMP(ms.session_stop)-UNIX_TIMESTAMP(ms.session_start)) AS diff FROM `map_sessions` ms JOIN positions p ON (ms.id=p.map_session_id) WHERE ms.map_id IN (196) AND p.timestamp > '2019-08-31 01:00:00' AND p.timestamp <= '2019-09-05 12:00:00' GROUP BY ts_interval ORDER BY ts_interval ASC
J'utilise des double pour stocker les lat/lng. J'utilise un datetime pour le timestamp.
Et voici le souci :
quand on a quelques dizaines de milliers de lignes, ça passe bien, mais quand on passe sur des centaines de milliers de lignes, ça commence à prendre quelques secondes (10s environ).
Je cherche donc à optimiser tout ça.
Voici plusieurs pistes que je pourrais explorer :
- faire des tables de cache avec agrégat, pré groupement au mètre, et à la minute (on ne descend jamais en dessous de la minute sur mes requêtes).
- Passer dans cette même table les lat/lng en entier, le temps en entier de type minute.
- Avoir plusieurs tables de cache avec différents niveau de groupement de temps... ???
- Utiliser des tables partitionnées ??? Partitionner par map_id/map_session_id, ou par année ? mois ? jour ?
Qu'en pensez vous ?
Merci!
Partager