I have a table that has a foreign key to a table that stores some blob data. When I do an inner join on the tables with a condition on the main table the join type goes from ‘index’ to ‘ALL’. I would like to avoid this as my blob table is on the order of tens of gigabytes. How can I avoid it?
Here is the the basic inner join:
EXPLAIN SELECT m.id, b.id, b.data
FROM metadata m, blobstore b
WHERE m.fkBlob = b.id;
1, 'SIMPLE', 'm', 'index', 'fk_blob', 'fk_blob', '4', '', 1, 'Using index'
1, 'SIMPLE', 'b', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'blob_index.m.fkBlob', 1, ''
Here I add a condition on the main table:
EXPLAIN SELECT m.id, b.id, b.data
FROM metadata m, blobstore b
WHERE m.fkBlob = b.id AND m.start < '2009-01-01';
1, 'SIMPLE', 'b', 'ALL', 'PRIMARY', '', '', '', 1, ''
1, 'SIMPLE', 'm', 'ref', 'fk_blob,index_start', 'fk_blob', '4', 'blob_index.b.id', 1, 'Using where'
Notice that the order in which the tables are listed has changed. It is now doing a full table scan on the blob table because of a condition I’ve added regarding the main table.
Here is the schema:
DROP TABLE IF EXISTS `blob_index`.`metadata`;
CREATE TABLE `blob_index`.`metadata` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fkBlob` int(10) unsigned NOT NULL,
`start` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_blob` (`fkBlob`),
KEY `index_start` (`start`),
CONSTRAINT `fk_blob` FOREIGN KEY (`fkBlob`) REFERENCES `blobstore` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `blob_index`.`blobstore`;
CREATE TABLE `blob_index`.`blobstore` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`data` mediumblob NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I guess you are trying this on empty table (because MySQL thinks it needs to go through one row to do full table scan), what might influence results of scheduler. When you will do it on real table, the
EXPLAINresults might vary (and actually did vary in my test).