优化查询以连接MySQL中的键/值对表

时间:2018-10-15 12:24:28

标签: mysql database

我尝试了多个主题,也遇到了自己的尝试和错误,但无法获得以下查询来加快速度。该查询工作正常,但速度非常慢:)

我已阅读并尝试过的主题:

Need Help for Optimizing MySQL query with few joins

MySQL select from key/value pairs table

Inner Joining two tables based on all "Key/Value" Pairs matching exactly

Merging the result of two INNER JOINS of the same table into one single temporary table in 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

item_id表中的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)"

0 个答案:

没有答案