Cláudio Ribeiro
Cláudio Ribeiro

Reputation: 1699

Improve Mysql query performance (index in type using explain)

Hi everyone I have the following database:

`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, ''

And the following query:

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%';

When using explain in this query I get the index result in the type field of the Users query. My question is, is there any way to improve this query so it improves this result. I understand the index means it goes through all the entries on that particular table, and that may be necessary in this case.

But do you guys see other ways of improving this?

EDIT: Showing indexes for galleries and images tables:

Galleries:

'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:

'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', '', ''

And the explain on the query already without the Users 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'

Upvotes: 0

Views: 71

Answers (2)

Rick James
Rick James

Reputation: 142316

(This partially disagrees with Gordon's answer.)

Since the WHERE only mentions images (WHERE i.description LIKE '%dog%'), the Optimizer will probably start with that table. No regular index is useful for that. (Gordon's comment on FULLTEXT is the 'right' way to improve that.)

The second table is easy to get to if id is the PRIMARY KEY. Please provide SHOW CREATE TABLE so we can see what indexes you have.

(I agree with the rest of Gordon's Answer.)

Another issue... If the tables become 'huge', you will find that UUIDs perform poorly (because of the randomness). A million rows is OK, a billion rows will be very slow.

Upvotes: 1

Gordon Linoff
Gordon Linoff

Reputation: 1270091

First, you can change the left join to inner join -- the where clause is already doing that, but be explicit. You can also get rid of users, because it is not used.

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%';

This query should be fine with indexes on images(gallery_id).

If performance is really an issue, you may want to investigate full text indexes so you can possibly change the like to match().

Upvotes: 1

Related Questions