Есть несколько тем, которые я пробовал, и мои собственные пробные версии и ошибки, но я не могу ускорить выполнение следующего запроса.Запрос работает нормально, но просто ужасно медленно:)
Темы, которые я прочитал и попробовал:
Нужна помощь для оптимизации запроса MySQL с несколькими объединениями
MySQL выбирает из таблицы пар ключ / значение
Внутреннее Объединение двух таблиц на основе всех пар «ключ / значение», точно совпадающих
Объединение результата двух ВНУТРЕННИХ СОЕДИНЕНИЙ одной и той же таблицы в одну временную таблицу в SQL Server
Вот мой запрос:
SELECT `users`.`id`,`users`.`name`,`users`.`email`
FROM `test_users` AS `users`
LEFT JOIN `test_fields_values` AS `fields_values` ON
`fields_values`.`item_id` = `users`.`id`
INNER JOIN `test_fields_values` AS `fields_values_lastname` ON
`users`.`id` = `fields_values_lastname`.`item_id`
WHERE
(`fields_values`.`field_id` IS NOT NULL) AND
(`fields_values_lastname`.`field_id` = 13)
GROUP BY `users`.`id`
ORDER BY `fields_values_lastname`.`value`
Таблицы выглядят какследующим образом.Таблица пользователя:
id | name | email
--------------------------------
1 | Myself | myself@example.com
Таблица fields_values вместо фактического значения, которое я ввел в имя поля, чтобы его было легче понять, я надеюсь.
field_id | item_id | value
------------------------------------------------------------
4 | 1 | Address
5 | 1 | Phone
6 | 1 | City
7 | 1 | Zipcode
8 | 1 | Email
9 | 1 | Country
10 | 1 | Lastname
11 | 1 | H
12 | 1 | I
13 | 1 | J
14 | 1 | K
15 | 1 | L
16 | 1 | M
17 | 1 | N
The *Поле 1030 * в таблице fields_values
соответствует полю id
в таблице users
.
Моя цель заключается в следующем:
Таблица user
содержит около 5500 записей вв нем и в таблице field_values
есть 13 записей для каждого пользователя.Сейчас я получаю список пользователей, упорядоченных по фамилии, и показываю их в списке.В этом списке есть фильтр, поэтому список пользователей можно фильтровать по стране / городу и общему поиску.
Фильтры применяются к полю value
таблицы fields_values
.Так что я могу получить всех пользователей, живущих в Бельгии, например.
Для каждого фильтра я добавляю еще один innerJoin, и поэтому запрос выглядит так:
SELECT `users`.`id`,`users`.`name`,`users`.`email`
FROM `test_users` AS `users`
LEFT JOIN `test_fields_values` AS `fields_values` ON
`fields_values`.`item_id` = `users`.`id`
INNER JOIN `test_fields_values` AS `fields_values_lastname` ON
`users`.`id` = `fields_values_lastname`.`item_id`
INNER JOIN `test_fields_values` AS `fields_values_country` ON
`users`.`id` = `fields_values_country`.`item_id`
WHERE
(
(`fields_values`.`field_id` IS NOT NULL) AND
(`fields_values_lastname`.`field_id` = 13)) AND
(`fields_values_country`.`value` = 'belgium')
GROUP BY `users`.`id`
ORDER BY `fields_values_lastname`.`value`
Даже без применения фильтров список занимаеткак 2,5 минуты для загрузки и EXPLAIN
показывает мне, что он извлек 73979 записей, что примерно равно 5500 * 13.
Любые подсказки / советы / улучшения приветствуются.Спасибо.
Редактировать:
users
стол
CREATE TABLE `test_users` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`username` VARCHAR(150) NOT NULL DEFAULT '',
`email` VARCHAR(100) NOT NULL DEFAULT '',
`password` VARCHAR(100) NOT NULL DEFAULT '',
`usertype` VARCHAR(25) NOT NULL DEFAULT '',
`block` TINYINT(4) NOT NULL DEFAULT '0',
`sendEmail` TINYINT(4) NULL DEFAULT '0',
`registerDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastvisitDate` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`activation` VARCHAR(100) NOT NULL DEFAULT '',
`params` TEXT NOT NULL,
PRIMARY KEY (`id`),
INDEX `usertype` (`usertype`),
INDEX `idx_name` (`name`),
INDEX `idx_block` (`block`),
INDEX `username` (`username`),
INDEX `email` (`email`)
)
COLLATE='utf8_general_ci';
fields_values
стол
CREATE TABLE `test_fields_values` (
`field_id` INT(10) UNSIGNED NOT NULL,
`item_id` VARCHAR(255) NOT NULL COMMENT 'Allow references to items which have strings as ids, eg. none db systems.' COLLATE 'utf8mb4_unicode_ci',
`value` TEXT NOT NULL COLLATE 'utf8mb4_unicode_ci',
INDEX `idx_field_id` (`field_id`),
INDEX `idx_item_id` (`item_id`(191))
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
Настоящим пояснение:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
"1" | "SIMPLE" | "fields_values_lastname" | "ref" | "idx_field_id,idx_item_id" | "idx_field_id" | "4" | "const" | "3513" | "Using temporary; Using filesort"
"1" | "SIMPLE" | "users" | "eq_ref" | "PRIMARY" | "PRIMARY" | "4" | "cms_inter.fields_values_lastname.item_id" | "1" | "Using where"
"1" | "SIMPLE" | "fields_values" | "ALL" | "id_id,idx_item_id" | NULL | NULL | NULL | "73979" | "Using where; Using join buffer (flat, BNL join)"