提高 Mysql 查询性能(索引类型使用解释)
Improve Mysql query performance (index in type using explain)
大家好,我有以下数据库:
`Users`
'id', 'char(36)', 'NO', 'PRI', NULL, ''
'password', 'varchar(64)', 'NO', '', NULL, ''
'email', 'varchar(60)', 'NO', 'UNI', NULL, ''
'roles', 'longtext', 'NO', '', NULL, ''
'is_active', 'tinyint(1)', 'NO', '', NULL, ''
`Galleries`
'id', 'char(36)', 'NO', 'PRI', NULL, ''
'user_id', 'char(36)', 'NO', 'MUL', NULL, ''
'name', 'varchar(255)', 'NO', '', NULL, ''
'description', 'longtext', 'YES', '', NULL, ''
'created_at', 'datetime', 'NO', '', NULL, ''
`Images`
'id', 'char(36)', 'NO', 'PRI', NULL, ''
'gallery_id', 'char(36)', 'YES', 'MUL', NULL, ''
'original_filename', 'varchar(255)', 'NO', '', NULL, ''
'filename', 'varchar(255)', 'NO', '', NULL, ''
'description', 'longtext', 'YES', '', NULL, ''
以及以下查询:
SELECT gal.name, gal.description, img.filename, img.description FROM `homestead`.`users` AS users
LEFT JOIN `homestead`.`galleries` AS gal ON users.id = gal.user_id
LEFT JOIN `homestead`.`images` AS img on img.gallery_id = gal.id
WHERE img.description LIKE '%dog%';
在此查询中使用 explain
时,我在用户查询的 type
字段中得到 index
结果。我的问题是,是否有任何方法可以改进此查询以改进此结果。我理解 index
意味着它会遍历该特定 table 上的所有条目,在这种情况下这可能是必要的。
但是你们看到其他改进方法了吗?
编辑:显示图库和图片的索引tables:
画廊:
'galleries', '0', 'PRIMARY', '1', 'id', 'A', '1', NULL, NULL, '', 'BTREE', '', ''
'galleries', '0', 'UNIQ_F70E6EB7BF396750', '1', 'id', 'A', '1', NULL, NULL, '', 'BTREE', '', ''
'galleries', '1', 'IDX_F70E6EB7A76ED395', '1', 'user_id', 'A', '1', NULL, NULL, '', 'BTREE', '', ''
图片:
'images', '0', 'PRIMARY', '1', 'id', 'A', '4', NULL, NULL, '', 'BTREE', '', ''
'images', '0', 'UNIQ_E01FBE6ABF396750', '1', 'id', 'A', '4', NULL, NULL, '', 'BTREE', '', ''
'images', '1', 'IDX_E01FBE6A4E7AF8F', '1', 'gallery_id', 'A', '4', NULL, NULL, 'YES', 'BTREE', '', ''
并且在没有用户的情况下对查询的解释 table:
'1', 'SIMPLE', 'gal', NULL, 'ALL', 'PRIMARY,UNIQ_F70E6EB7BF396750', NULL, NULL, NULL, '1', '100.00', NULL
'1', 'SIMPLE', 'img', NULL, 'ref', 'IDX_E01FBE6A4E7AF8F', 'IDX_E01FBE6A4E7AF8F', '109', 'homestead.gal.id', '1', '25.00', 'Using where'
首先,您可以将 left join
更改为 inner join
—— where
子句已经这样做了,但要明确。也可以去掉users
,因为没用到
SELECT g.name, g.description, i.filename, i.description
FROM `homestead`.`galleries` g INNER JOIN
`homestead`.`images` i
ON i.gallery_id = g.id
WHERE i.description LIKE '%dog%';
此查询应该适用于 images(gallery_id)
.
上的索引
如果性能确实是个问题,您可能需要调查全文索引,这样您就可以将 like
更改为 match()
。
(这部分不同意戈登的回答。)
由于 WHERE
仅提及 images
(WHERE i.description LIKE '%dog%'
),优化器可能会从 table 开始。没有常规索引对此有用。 (戈登对 FULLTEXT
的评论是 'right' 改进的方法。)
如果 id
是 PRIMARY KEY
,那么第二个 table 很容易到达。请提供 SHOW CREATE TABLE
以便我们查看您有哪些索引。
(我同意戈登回答的其余部分。)
另一个问题...如果table变成了'huge',你会发现UUID表现很差(因为随机性)。一百万行可以,十亿行会很慢。
大家好,我有以下数据库:
`Users`
'id', 'char(36)', 'NO', 'PRI', NULL, ''
'password', 'varchar(64)', 'NO', '', NULL, ''
'email', 'varchar(60)', 'NO', 'UNI', NULL, ''
'roles', 'longtext', 'NO', '', NULL, ''
'is_active', 'tinyint(1)', 'NO', '', NULL, ''
`Galleries`
'id', 'char(36)', 'NO', 'PRI', NULL, ''
'user_id', 'char(36)', 'NO', 'MUL', NULL, ''
'name', 'varchar(255)', 'NO', '', NULL, ''
'description', 'longtext', 'YES', '', NULL, ''
'created_at', 'datetime', 'NO', '', NULL, ''
`Images`
'id', 'char(36)', 'NO', 'PRI', NULL, ''
'gallery_id', 'char(36)', 'YES', 'MUL', NULL, ''
'original_filename', 'varchar(255)', 'NO', '', NULL, ''
'filename', 'varchar(255)', 'NO', '', NULL, ''
'description', 'longtext', 'YES', '', NULL, ''
以及以下查询:
SELECT gal.name, gal.description, img.filename, img.description FROM `homestead`.`users` AS users
LEFT JOIN `homestead`.`galleries` AS gal ON users.id = gal.user_id
LEFT JOIN `homestead`.`images` AS img on img.gallery_id = gal.id
WHERE img.description LIKE '%dog%';
在此查询中使用 explain
时,我在用户查询的 type
字段中得到 index
结果。我的问题是,是否有任何方法可以改进此查询以改进此结果。我理解 index
意味着它会遍历该特定 table 上的所有条目,在这种情况下这可能是必要的。
但是你们看到其他改进方法了吗?
编辑:显示图库和图片的索引tables:
画廊:
'galleries', '0', 'PRIMARY', '1', 'id', 'A', '1', NULL, NULL, '', 'BTREE', '', ''
'galleries', '0', 'UNIQ_F70E6EB7BF396750', '1', 'id', 'A', '1', NULL, NULL, '', 'BTREE', '', ''
'galleries', '1', 'IDX_F70E6EB7A76ED395', '1', 'user_id', 'A', '1', NULL, NULL, '', 'BTREE', '', ''
图片:
'images', '0', 'PRIMARY', '1', 'id', 'A', '4', NULL, NULL, '', 'BTREE', '', ''
'images', '0', 'UNIQ_E01FBE6ABF396750', '1', 'id', 'A', '4', NULL, NULL, '', 'BTREE', '', ''
'images', '1', 'IDX_E01FBE6A4E7AF8F', '1', 'gallery_id', 'A', '4', NULL, NULL, 'YES', 'BTREE', '', ''
并且在没有用户的情况下对查询的解释 table:
'1', 'SIMPLE', 'gal', NULL, 'ALL', 'PRIMARY,UNIQ_F70E6EB7BF396750', NULL, NULL, NULL, '1', '100.00', NULL
'1', 'SIMPLE', 'img', NULL, 'ref', 'IDX_E01FBE6A4E7AF8F', 'IDX_E01FBE6A4E7AF8F', '109', 'homestead.gal.id', '1', '25.00', 'Using where'
首先,您可以将 left join
更改为 inner join
—— where
子句已经这样做了,但要明确。也可以去掉users
,因为没用到
SELECT g.name, g.description, i.filename, i.description
FROM `homestead`.`galleries` g INNER JOIN
`homestead`.`images` i
ON i.gallery_id = g.id
WHERE i.description LIKE '%dog%';
此查询应该适用于 images(gallery_id)
.
如果性能确实是个问题,您可能需要调查全文索引,这样您就可以将 like
更改为 match()
。
(这部分不同意戈登的回答。)
由于 WHERE
仅提及 images
(WHERE i.description LIKE '%dog%'
),优化器可能会从 table 开始。没有常规索引对此有用。 (戈登对 FULLTEXT
的评论是 'right' 改进的方法。)
如果 id
是 PRIMARY KEY
,那么第二个 table 很容易到达。请提供 SHOW CREATE TABLE
以便我们查看您有哪些索引。
(我同意戈登回答的其余部分。)
另一个问题...如果table变成了'huge',你会发现UUID表现很差(因为随机性)。一百万行可以,十亿行会很慢。