MySQL query not using primary key, I don't understand why - mysql

I have a table called product categories. Structure is as follows:
+---------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+-------+
| sku | char(50) | NO | PRI | | |
| sorting_field | char(20) | NO | PRI | | |
| category | char(255) | NO | PRI | | |
| hide | tinyint(1) | NO | PRI | 0 | |
+---------------+------------+------+-----+---------+-------+
The following query runs an excessive amount of time on this table:
SELECT category FROM product_categories WHERE hide!=1 AND sorting_field="item_type" GROUP BY category;
When I run EXPLAIN, I get the following result:
+----+-------------+-----------------------------+-------+---------------+---------+---------+------+-------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------------------+-------+---------------+---------+---------+------+-------+-----------------------------------------------------------+
| 1 | SIMPLE | product_categories | index | NULL | PRIMARY | 976 | NULL | 43568 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-----------------------------+-------+---------------+---------+---------+------+-------+-----------------------------------------------------------+
I don't understand why this is happening at all! Why is the primary key not considered a possible key? This just doesn't make sense to me. By the way, here is the result of SHOW KEYS on this table:
+-----------------------------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------------------------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| product_categories | 0 | PRIMARY | 1 | sku | A | 8713 | NULL | NULL | | BTREE | |
| product_categories | 0 | PRIMARY | 2 | sorting_field | A | 43568 | NULL | NULL | | BTREE | |
| product_categories | 0 | PRIMARY | 3 | category | A | 43568 | NULL | NULL | | BTREE | |
| product_categories | 0 | PRIMARY | 4 | hide | A | 43568 | NULL | NULL | | BTREE | |
+-----------------------------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
Can anybody shed light on this dilemma for me?

If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to find rows.
Your index is (sku, sorting_field, category, hide), so you have index search capabilities on (sku), (sku, sorting_field), (sku, sorting_field, category) and (sku, sorting_field, category, hide).
In other words if you change your primary key to (sorting_field, hide, sku, category), primary key became a possible key of your query.
However i think you could find better solutions. For example:
create table product_categories (
sku char(50) not null,
sorting_field char(20) not null,
category char(255) not null,
hide tinyint(1) not null,
Primary key (sku, category),
key sorting_field (sorting_field, hide))

The possible_keys column of EXPLAIN is just a list of possibilities. The key column is what's actually going to be used in the query, and in your case, it's showing that it will use the PRIMARY.

Related

Why is MySQL not using my index for JOIN?

I have an incredibly complex query being produced by an ORM, but here's the relevant portions for the sake of this question:
SELECT
...
FROM
`Broadcast` `t`
LEFT OUTER JOIN
`Site` `site`
ON (`t`.`site_id` = `site`.`id`)
LEFT OUTER JOIN
`Customer` `customer`
ON (`site`.`customer_id` = `customer`.`id`)
LEFT OUTER JOIN
`Domain` `domain`
ON (`customer`.`domain_id` = `domain`.`id`)
...
My fields are defined as follows:
>SHOW FIELDS FROM Broadcast;
+---------------------------+--------------------------------------+------+-----+------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+--------------------------------------+------+-----+------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| site_id | int(10) unsigned | NO | MUL | NULL | |
...
>SHOW FIELDS FROM Site;
+---------------------------+---------------------+------+-----+------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+---------------------+------+-----+------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| customer_id | int(11) | NO | MUL | 0 | |
...
>SHOW FIELDS FROM Customer;
+---------------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| domain_id | int(10) unsigned | NO | MUL | 1 | |
...
>SHOW FIELDS FROM Domain;
+---------------------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
...
Why some of our IDs are int(11) and others are int(10) unsigned is just a matter of historical context. What's important is that the X_id foreign key always shares a type with the relevant id column. We never attempt to link an int(11) with an int(10) unsigned. Also the id field is always the primary key for the table.
We also have indexes on all of the foreign keys:
>SHOW INDEXES FROM Broadcast;
+-----------+------------+---------------------------------------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+---------------------------------------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Broadcast | 0 | PRIMARY | 1 | id | A | 139708 | NULL | NULL | | BTREE | | |
| Broadcast | 1 | site_id | 1 | site_id | A | 1060 | NULL | NULL | | BTREE | | |
...
>SHOW INDEXES FROM Site;
+-------+------------+----------------------------------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------------------------------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Site | 0 | PRIMARY | 1 | id | A | 1876 | NULL | NULL | | BTREE | | |
| Site | 1 | customer_id | 1 | customer_id | A | 250 | NULL | NULL | | BTREE | | |
...
>SHOW INDEXES FROM Customer;
+----------+------------+--------------------------------------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+--------------------------------------+--------------+---------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Customer | 0 | PRIMARY | 1 | id | A | 292 | NULL | NULL | | BTREE | | |
| Customer | 1 | domain_id | 1 | domain_id | A | 2 | NULL | NULL | | BTREE | | |
...
>SHOW INDEXES FROM Domain;
+--------+------------+-------------------------------------------+--------------+---------------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+-------------------------------------------+--------------+---------------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Domain | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
...
Each of these indexes consists of a single field, so the field is the first sequence in the index.
When I run EXPLAIN ... on my query, the output I get looks as follows:
Site and Customer are joined with the eq_ref type, but Domain is joined with ALL type. Why is MySQL not using my index?
I can force MySQL to use my index by adding USE INDEX FOR JOIN (domain_id) after the Customer table name, but this causes a new issue:
The problem just moves up from the Customer->Domain relation to the Site->Customer relation. I can shift the problem up one further using USE INDEX FOR JOIN (customer_id) after the Site table name, and as you might expect this just causes the Site table to join with the ALL type instead of eq_ref
I can't for the life of me figure out why MySQL is refusing to use my indexes
Per #ysth in the comments:
MySQL will not use an index if the table you are joining has very few rows, as the overhead of reading an index from disk exceeds the benefits

mysql - slow query due to high index cardinality

I've got the following mysql query taking approx 55 seconds to complete
SELECT this_.id AS y0_ FROM event this_
INNER JOIN member m1_ ON this_.member_id=m1_.id
INNER JOIN event_type et2_ ON this_.type_id=et2_.id
WHERE m1_.submission_id=40646 AND et2_.name IN ('Salary')
ORDER BY m1_.ni_number ASC, m1_.ident1 ASC, m1_.ident2 ASC, m1_.ident3 ASC, m1_.id ASC, et2_.name ASC LIMIT 15;
If I remove the join/where/order to the 'event_type' table, then the query runs in under 1 second.
So something clearly up with my join to the 'event_type' table, but a similar query in another database with similar database volumes runs absolutely fine. So my suspicion is something wrong with this 1 database.
The 'show create table' of the 'event' table is:
Create Table: CREATE TABLE `event` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`data_size` bigint(20) DEFAULT NULL,
`encoded_data` mediumblob,
`last_updated` datetime NOT NULL,
`member_id` bigint(20) NOT NULL,
`parent_event_id` bigint(20) DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`type_id` bigint(20) NOT NULL,
`updated_by` varchar(255) NOT NULL,
`failed_workflow_case` varchar(255) DEFAULT NULL,
`failed_workflow_task` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK5C6729A2434DA80` (`member_id`),
KEY `FK5C6729AE4E22C6E` (`type_id`),
KEY `IND_parent_event_id` (`parent_event_id`),
CONSTRAINT `FK5C6729A2434DA80` FOREIGN KEY (`member_id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK5C6729AE4E22C6E` FOREIGN KEY (`type_id`) REFERENCES `event_type` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=46241198 DEFAULT CHARSET=latin1
The EXPLAIN of the query is:
+----+-------------+-------+------------+--------+-------------------------------------+-------------------+---------+--------------------------+------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+-------------------------------------+-------------------+---------+--------------------------+------+----------+----------------------------------------------+
| 1 | SIMPLE | et2_ | NULL | ref | PRIMARY,IND_name | IND_name | 257 | const | 1 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | this_ | NULL | ref | FK5C6729A2434DA80,FK5C6729AE4E22C6E | FK5C6729AE4E22C6E | 8 | iconnect.et2_.id | 3303 | 100.00 | NULL |
| 1 | SIMPLE | m1_ | NULL | eq_ref | PRIMARY,IND_submission_id | PRIMARY | 8 | iconnect.this_.member_id | 1 | 5.00 | Using where |
+----+-------------+-------+------------+--------+-------------------------------------+-------------------+---------+--------------------------+------+----------+----------------------------------------------+
The indexes from the 'event' table are:
+-------+------------+---------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+---------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| event | 0 | PRIMARY | 1 | id | A | 14307622 | NULL | NULL | | BTREE | | |
| event | 1 | FK5C6729A2434DA80 | 1 | member_id | A | 4680601 | NULL | NULL | | BTREE | | |
| event | 1 | FK5C6729AE4E22C6E | 1 | type_id | A | 4360 | NULL | NULL | | BTREE | | |
| event | 1 | IND_parent_event_id | 1 | parent_event_id | A | 114404 | NULL | NULL | YES | BTREE | | |
+-------+------------+---------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
What jumps out at me from this is:
1. why is the EXPLAIN going through 3303 rows and the FK5C6729AE4E22C6E index?
2. why does the FK5C6729AE4E22C6E index have a cardinality of 4360 when there are only 17 rows in the 'event_type' table? could this incorrect cardinality be affecting the query optimizer?
I've done an ANALYZE TABLE on both 'event' and 'event_type' and this has made no difference.
Any suggestions?
execute plan from other server with the same data (loaded from a dump file):
+----+-------------+-------+------------+------+-------------------------------------+-------------------+---------+-----------------+-------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------------------------+-------------------+---------+-----------------+-------+----------+----------------------------------------------+
| 1 | SIMPLE | et2_ | NULL | ALL | PRIMARY | NULL | NULL | NULL | 17 | 10.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | m1_ | NULL | ref | PRIMARY,IND_submission_id | IND_submission_id | 8 | const | 27992 | 100.00 | NULL |
| 1 | SIMPLE | this_ | NULL | ref | FK5C6729A2434DA80,FK5C6729AE4E22C6E | FK5C6729A2434DA80 | 8 | iconnect.m1_.id | 3 | 11.11 | Using where |
+----+-------------+-------+------------+------+-------------------------------------+-------------------+---------+-----------------+-------+----------+----------------------------------------------+
Increasing innodb_stats_persistent_sample_pages from 20 to 100, then running ANALYZE TABLE on event/member tables changed the cardinality of the indexes and the execution plan, then the query ran in under 1 second. Thanks to Solarflare for the suggestion.

MySQL latency caused by using index; Using temporary; Using filesort

I have a query that joins two tables and orders the data on the primary key. This is resulting in the very popular problem of MySQL "Using index; Using temporary; Using filesort."
The issue is causing a severe latency problem in my production tables with about 400k records.
Here's more info:
I have two tables: Doctor and Area. The Doctor table has a foreign key pointing to Area.
Doctor:
+-----------------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| area_id | int(11) | NO | MUL | NULL | |
+-----------------------------+---------------+------+-----+---------+----------------+
Doctor indexes:
+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| doctor | 0 | PRIMARY | 1 | id | A | 5546 | NULL | NULL | | BTREE | | |
| doctor | 1 | doctor_dfd0e917 | 1 | area_id | A | 29 | NULL | NULL | | BTREE | | |
+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
Area:
+------------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
+------------------------+-------------+------+-----+---------+----------------+
And the Area indexes:
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| area | 0 | PRIMARY | 1 | id | A | 24 | NULL | NULL | | BTREE | | |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
I'm trying to run the following query:
SELECT `doctor`.`id`,
`area`.`id`
FROM
`doctor`
INNER JOIN
`area` ON (`doctor`.`area_id` = `area`.`id`)
ORDER BY
`doctor`.`id` DESC LIMIT 100;
The EXPLAIN returns the following (with the problematic Using index; Using temporary; Using filesort):
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
| 1 | SIMPLE | area | index | PRIMARY | PRIMARY | 4 | NULL | 24 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | doctor | ref | doctor_dfd0e917 | doctor_dfd0e917 | 4 | area.id | 191 | Using index |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
If I remove the ORDER BY clause, I get the desired effect:
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
| 1 | SIMPLE | area | index | PRIMARY | PRIMARY | 4 | NULL | 24 | Using index |
| 1 | SIMPLE | doctor | ref | doctor_dfd0e917 | doctor_dfd0e917 | 4 | area.id | 191 | Using index |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
Why is the ORDER BY clause causing problems here even though I'm using the primary key?
Thank you in advance.
It seems that you only have one area per doctor. See how this query works:
SELECT d.id,
(SELECT a.id FROM area a ON a.id = d.area_id) as area_id
FROM doctor d
ORDER BY d.id DESC
LIMIT 100;
If you are using inner join to test for the presence of a doctor in the table, then add:
SELECT d.id,
(SELECT a.id FROM area a ON a.id = d.area_id) as area_id
FROM doctor d
WHERE EXISTS (SELECT 1 FROM area a ON a.id = d.area_id)
ORDER BY d.id DESC
LIMIT 100;
There is a good chance that both of these will scan the doctors table in order, picking up the information from area as needed.

MySQL: 'EXPLAIN' showing different explanations for similar queries

I have a table 'posts' in database which has non-unique index on user_id (Key: MUL).
mysql> show columns from posts;
+---------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | MUL | NULL | |
| post | varchar(140) | NO | | NULL | |
+---------+--------------+------+-----+-------------------+----------------+
For this table, explain gives expected explanation where type is 'REF'
mysql> explain select * from posts where posts.user_id=1;
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
| 1 | SIMPLE | posts | ref | user_id | user_id | 5 | const | 74 | Using where |
+----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
I have a second table 'followers' where 'user_id' and 'follower' are part of non-unique index
mysql> show columns from followers;
+---------------+-----------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-----------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | MUL | NULL | |
| follower | int(11) | YES | MUL | NULL | |
+---------------+-----------+------+-----+---------------------+----------------+
But in this table, type is 'ALL'. I expected it to be 'REF' as similar to 'user_id' in previous table, this 'user_id' also has non-unique index. Is there any explanation for this?
mysql> explain select * from followers where followers.user_id=1;
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | followers | ALL | user_id | NULL | NULL | NULL | 6 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
I'll post it as an answer, cause I'm pretty sure this is the case.
I think you get differences because in followers table you have a composite key from both user_id and follower fields, rather than just a key on user_id.
Therefore index will be used for queries that use both user_id AND follower in WHERE clause.
Add a separate index on user_id field and you will get the same explanation.

MySQL Inconsistencies in index usage on the same query

I have a table of over 9 million rows. I have a SELECT query that I'm using an index for. Here is the query:
SELECT `username`,`id`
FROM `04c1Tg0M`
WHERE `id` > 9259466
AND `tried` = 0
LIMIT 1;
That query executes very fast (0.00 sec). Here is the explain for that query:
+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+
| 1 | SIMPLE | 04c1Tg0M | range | PRIMARY,triedex | PRIMARY | 4 | NULL | 10822 | Using where |
+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+
Now here is the same query except that I'm going to change the id to 6259466:
SELECT `username`,`id`
FROM `04c1Tg0M`
WHERE `id` > 5986551
AND `tried` = 0
LIMIT 1;
That query took 4.78 seconds to complete. This is the problem. Here is the explain for that query:
+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+
| 1 | SIMPLE | 04c1Tg0M | ref | PRIMARY,triedex | triedex | 2 | const | 9275107 | Using where |
+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+
What is happening here and how can I fix it? Here are my indexes:
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| 04c1Tg0M | 0 | PRIMARY | 1 | id | A | 9275093 | NULL | NULL | | BTREE | |
| 04c1Tg0M | 1 | pdex | 1 | username | A | 9275093 | NULL | NULL | | BTREE | |
| 04c1Tg0M | 1 | pdex | 2 | id | A | 9275093 | NULL | NULL | | BTREE | |
| 04c1Tg0M | 1 | pdex | 3 | tried | A | 9275093 | NULL | NULL | YES | BTREE | |
| 04c1Tg0M | 1 | triedex | 1 | tried | A | 0 | NULL | NULL | YES | BTREE | |
| 04c1Tg0M | 1 | triedex | 2 | id | A | 9275093 | NULL | NULL | | BTREE | |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
And here is my table structure:
| 04c1Tg0M | CREATE TABLE `04c1Tg0M` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`tried` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `pdex` (`username`,`id`,`tried`),
KEY `triedex` (`tried`,`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9275108 DEFAULT CHARSET=utf8 |
The first SQL returns 10822 rows, while the second one returns 9275107 rows!
The use of primary key "id" index in the second query isn't so useful because you have to do a full table scan anyway.
MySQL's cost-based optimizer thinks, in the case of the 2nd query, it's better off to use the index on 'tried'.
If you have to do a full table-scan, you're better off not using an index, as index constitutes additional disk reads.
You can use "use index" or "force index" in your query to hint to the optimizer whether to use an index.
Also update the statistics by analyzing your table periodically so the cost-based optimizer is working correctly.