Я пытаюсь выяснить, каков наилучший способ оптимизации моего текущего запроса выбора в базе данных MySQL.
У меня есть 2 таблицы MySQL с отношением один-ко-многим .Одним из них является таблица user
, которая содержит уникальный список пользователей и имеет около 22krows .Одним из них является таблица linedata
, которая содержит все возможные координаты для каждого пользователя и имеет около 490k строк .
В этом случае можно предположить, что внешний ключ между двумя таблицами равен id
.В случае пользовательской таблицы идентификатор также является первичным ключом с автоинкрементом, в то время как в таблице linedata это не первичный ключ, поскольку мы можем иметь больше строк для одного и того же пользователя.
Структура CREATE STMT
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`isActive` tinyint(4) NOT NULL,
`userId` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`gender` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21938 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `linedata` (
`id` int(11) NOT NULL,
`userId` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`timestamp` datetime NOT NULL,
`x` float NOT NULL,
`y` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Запрос выбора
SELECT
u.id,
u.isActive,
u.userId,
u.name,
u.gender,
u.age,
GROUP_CONCAT(CONCAT_WS(', ',timestamp,x, y)
ORDER BY timestamp ASC SEPARATOR '; '
) as linedata_0
FROM user u
JOIN linedata l
ON u.id=l.id
WHERE DATEDIFF(l.timestamp, '2018-02-28T20:00:00.000Z') >= 0
AND DATEDIFF(l.timestamp, '2018-11-20T09:20:08.218Z') <= 0
GROUP BY userId;
Вывод EXPLAIN
+-------+---------------+-----------+-----------+-------------------+-----------+---------------+-----------+-----------+------------------------------------------------------------+
| ID | SELECT_TYPE | TABLE | TYPE | POSSIBLE_KEYS | KEY | KEY_LEN | REF | ROWS | EXTRA |
+-------+---------------+-----------+-----------+-------------------+-----------+---------------+-----------+-----------+------------------------------------------------------------+
| 1 | SIMPLE | l | ALL | NULL | NULL | NULL | NULL | 491157 | "Using where; Using temporary; Using filesort" |
+-------+---------------+-----------+-----------+-------------------+-----------+---------------+-----------+-----------+------------------------------------------------------------+
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | l.id | 1 | NULL |
+-------+---------------+-----------+-----------+-------------------+-----------+---------------+-----------+-----------+------------------------------------------------------------+
Запрос выбора работает, если, например, я добавлю еще одно условие WHERE для фильтрации отдельных пользователей.Допустим, я хочу выбрать только 200 пользователя, тогда я получил около 14 секунд в качестве времени выполнения.Около 7 секунд , если я выберу только первых 100 пользователей .Но в случае наличия только условия диапазона даты и времени загрузка кажется без конечной точки.Есть какие-нибудь предложения?
ОБНОВЛЕНИЕ
После выполнения рекомендаций Рика тестовый запрос составляет около 14 секунд.Здесь ниже EXPLAIN EXTENDED
:
id, select_type, таблица, тип, возможные_ключи, ключ, key_len, ref, строки, отфильтрованные, Extra 1, PRIMARY, u, index, PRIMARY,PRIMARY, 4, NULL, 21959,100.00, NULL 1, PRIMARY, l, ref, id_timestamp_index, id_timestamp_index, 4, u.id, 14,100.00, «Использование условия индекса» 2, «ЗАВИСИМАЯ ПОДПИСЬ», NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, «Таблицы не используются»
Я немного изменил некоторые значения таблиц:
Где id
в пользовательской таблице может быть объединен с userId
в таблице линеаданных.И теперь они целые.У нас будет строковый тип только для значения userId в пользовательской таблице, потому что это своего рода длинный строковый идентификатор, такой как 0000309ab2912b2fd34350d7e6c079846bb6c5e1f97d3ccb053d15061433e77a_0 .
Итак, просто для краткого примера мы будем иметь в user
и в linedata
таблице:
+-------+-----------+-----------+-------------------+--------+---+
| id | isActive | userId | name | gender |age|
+-------+-----------+-----------+-------------------+--------+---+
| 1 | 1 | x4by4d | john | m | 22|
| 2 | 1 | 3ub3ub | bob | m | 50|
+-------+-----------+-----------+-------------------+--------+---+
+-------+-----------+-----------+------+---+
| id | userId |timestamp | x | y |
+-------+-----------+-----------+------+----+
| 1 | 1 | somedate | 30 | 10 |
| 2 | 1 | somedate | 45 | 15 |
| 3 | 1 | somedate | 50 | 20 |
| 4 | 2 | somedate | 20 | 5 |
| 5 | 2 | somedate | 25 | 10 |
+-------+-----------+-----------+------+----+
Я добавил составной индекс madeuserId
и timestamp
значений в таблице linedata.
Возможно, вместо того, чтобы иметь в качестве первичного ключа значение ai id для таблицы linedata
, если я добавлю составной первичный ключ , сделанныйuserId
+ timestamp
?Должно ли повысить производительность или нет?