Количество точек GPS в зависимости от режима движения - PullRequest
1 голос
/ 16 июня 2020

Я работаю над geolife набором данных . Это GPS набор данных о траектории почти 25 миллионов GPS точек пользователей. Итак, я создал две таблицы (фактически воспроизведенные из здесь) : plt_distinct, содержащие точки GPS пользователей (более 24 миллионов строк), и labels таблицу, содержащую режим передвижения, используемый участниками (14 718 строк).

CREATE TABLE `plt_distinct` (
  `directory` varchar(10) NOT NULL DEFAULT '',
  `latitude` double NOT NULL DEFAULT '0',
  `longitude` double NOT NULL DEFAULT '0',
  `flag` int(11) DEFAULT NULL,
  `altitude` double NOT NULL DEFAULT '0',
  `passeddate` varchar(255) DEFAULT NULL,
  `gpsdate` date NOT NULL DEFAULT '0000-00-00',
  `gpstime` time NOT NULL DEFAULT '00:00:00',
  `gpsdatetime` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`directory`,`latitude`,`longitude`,`gpsdate`,`gpstime`,`altitude`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `labels` (
  `directory` varchar(10) NOT NULL DEFAULT '',
  `starttime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `endtime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `transportationmode` varchar(10) NOT NULL DEFAULT '',
  PRIMARY KEY (`directory`,`starttime`,`endtime`,`transportationmode`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Я собираюсь провести некоторый исследовательский анализ (например, GPS частота дискретизации для каждого режима перемещения и c ..). Существует около десяти различных режимов движения для пользователей, как указано в labels.

Итак, для начала я хочу подсчитать количество точек GPS для каждого режима движения, поэтому я пишу:

SELECT COUNT(*) 
FROM labels JOIN plt_distinct 
USING (directory) 
WHERE transportationmode='bus';

+------------+
| COUNT(*)   |
+------------+
| 1881761963 |
+------------+
1 row in set (7 min 13.83 sec)

Этот запрос возвращает более 188 миллионов отсчетов, это более МИЛЛИАРДА, явно примерно в 80 раз больше доступных точек GPS в целом. Я знаю, что делаю что-то неправильно (не считая отдельных точек для режима шины), но я не уверен, как достичь своей цели.

Как MWE по моей проблеме (иллюстрируя, что я имею в виду), я создал db-fiddle здесь только с 5 строками из этих tables (и только 2 bus в режиме перемещения), но мой запрос возвращает количество десять.

Как я могу правильно подсчитать количество очков для каждого режима передвижения?

1 Ответ

0 голосов
/ 16 июня 2020

Комбинаторный взрыв из-за чрезмерно разрешающего предложения ON в JOIN.

В вашей скрипке ваш образец labels содержит эти строки.

directory | starttime           | endtime             | transportationmode
:-------- | :------------------ | :------------------ | :-----------------
179       | 2008-11-17 06:59:58 | 2008-11-17 07:06:16 | bus               
179       | 2008-11-17 07:06:16 | 2008-11-17 07:14:32 | walk              
179       | 2008-11-29 02:01:39 | 2008-11-29 02:07:57 | walk              
179       | 2008-11-29 02:07:57 | 2008-11-29 02:01:39 | bus               
179       | 2008-11-29 02:07:57 | 2008-11-29 02:43:37 | subway            

Обратите внимание, как Столбец transportationmode содержит повторяющиеся значения для bus и walk для одного и того же значения directory. Это означает, что ваше предложение

FROM plt_distinct JOIN labels ON plt_distinct.directory = labels.directory 

втягивает каждую строку в plt_distinct пять раз, по одному для каждой строки в labels. Это означает слишком много строк.

Я предполагаю, не будучи уверенным, что каждая строка в plt_distinct должна быть связана только с одной строкой в ​​labels. Возможно, вы могли бы сделать это, сопоставив временные метки, а также каталоги. (У вашего второго столбца labels.bus время окончания перед временем начала, поэтому трудно быть уверенным.)

Запрос с таким предложением ON сделает это.

SELECT *
  FROM labels 
  JOIN plt_distinct ON labels.directory = plt_distinct.directory
                   AND plt_distinct.gpsdatetime >= labels.starttime
                   AND plt_distinct.gpsdatetime <= labels.endtime;

Но между значениями gpsdatetime и starttime / endtime нет большого совпадения, поэтому я не уверен, что это правильно.

Для ваших данных потребуется способ поместить только один labels строка в каждой plt_distinct строке, если этот проект должен работать.

Совет для профессионалов Избегайте USING(column) в JOIN пунктах. Это действительно подвержено ошибкам.

...