I'm quite new to setting indexes myself. I'm currently just experimenting with it to discover how it works and in what cases a database will make use of the index.
I've got a simple table with 3 columns; an id, a name and a status. I've set an index on the name which is a CHAR(30) column. Against my expectations, MySQL ignores this index in the following query:
SELECT * FROM people WHERE name = 'Peter'
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE people ref name name 90 const 1 Using where
However, when using the following query, the index is used:
SELECT COUNT(*) FROM people WHERE name = 'Peter'
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE people ref name name 90 const 1 Using where; Using index
Could anyone please explain this to me?
"Using index" means it's using the index as a "covering index". This happens when it only needs to access the index to satisfy the query.
If, on the other hand, "Using index" is absent, but in the "key" column, the index is named, then it's using that index in the way described in the "ref" column.
So in both cases it's using the index, but only the COUNT() uses it as a covering index.
For each query, the "key" columns indicates "name" -- so, I'd say your two queries both used the index called "name", which probably is on the "name" column -- and this is what you want (quoting the manual) :
The key column indicates the key
(index) that MySQL actually decided to
use. If MySQL decides to use one of
the possible_keys indexes to look up
rows, that index is listed as the key
value.
Also, you are only going through "1" row, which is good (no full-scan or anything like that).
The "type" says "ref", which seems to be a good thing :
All rows with matching index values
are read from this table for each
combination of rows from the previous
tables. ... If the key that is used
matches only a few rows, this is a
good join type.
ref can be used for indexed columns
that are compared using the = or <=>
operator.
And the "ref" column indicates "const" -- not sure what it means exactly, but as far as I know, it's a good thing.
What makes you think your index is not used for one column ?
Just as a reference, for more informations : 7.2.1. Optimizing Queries with EXPLAIN
Related
I have the following query:
SELECT *
FROM table
WHERE
structural_type=1
AND parent_id='167F2-F'
AND points_to_id=''
# AND match(search) against ('donotmatch124213123123')
The search takes about 10ms to run, running on the composite index (structural_type, parent_id, points_to_id). However, when I add in the fts index, the query balloons to taking ~1s, regardless of what is contained in the match criteria. Basically it seems like it 'skips the index' whenever I have a fts search applied.
What would be the best way to optimize this query?
Update: a few explains:
EXPLAIN SELECT... # without fts
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table NULL ref structural_type structural_type 209 const,const,const 2 100.00 NULL
With fts (also adding 'force index'):
explain SELECT ... force INDEX (structural_type) AND match...
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE table NULL fulltext structural_type,search search 0 const 1 5.00 Using where; Ft_hints: sorted
The only thing I can think of which would be incredibly hack-ish, would be to add an additional term to the fts so it does the filter 'within' that. For example:
fts_term = fts_term += " StructuralType1ParentID167F2FPointsToID"
The MySQL optimizer can only use one index for your WHERE clause, so it has to choose between the composite one and the FULLTEXT one.
Since it can't run both queries to bench which one is faster, it will estimate how fast will different execution plans be.
To do so, MySQL uses some internal stats it keeps about each table. But those stats can be very different from the reality if they aren't updated and the data changes in the table.
Running a OPTIMIZE TABLE table query allows MySQL to refresh its table stats, so it will be able to perform better estimates and choose the better index.
Try expressing this without the full text logic, using like:
SELECT *
FROM table
WHERE structural_type = 1 AND
parent_id ='167F2-F' AND
points_to_id = '' AND
search not like '%donotmatch124213123123%';
The index should still be used for the first three columns. LIKE might be slow, but if not many rows match the first three, this might not be as bad as using the full text index.
I've been trying to use SQL EXPLAIN lately, And there is something werid with the PK Possible Keys and K Key,
I get for example the following row
[id - select_type - table - type - possible_keys - key - key_len - ref - rows - Extra]
[1 - PRIMARY - users - const - PRIMARY, username - username - 66 - const - 1 - using index; using temporary; using filesort]
What i understood that i must pick both PRIMARY and username as multiple index, But i can only have one PRIMARY key at the table for id, So does PK shows me keys that i'm supposed to select one of them?
You don't "pick an index" to use in a query; the Optimizer picks.
A PRIMARY KEY (PK) can have one or more columns in it. A table can have only one PK. Every table should have a PK.
A "secondary key" is any index other than the PK. It, too, can have one or more columns.
The Optimizer almost never uses more than one index (PK or some secondary) for a single SELECT.
"Possible keys" is those that the Optimizer thinks might work. After further analysis, it decides which one to use, and declares it in the "key" column. In your example, the Optimizer decided that INDEX "username" (...) would work better than PRIMARY KEY(...).
I am unclear on what you expect "multiple index" to mean...
There can be multiple indexes; but the Optimizer is unlikely to use more than one.
An index may have multiple columns in it.
A table can have multiple indexes.
The Optimizer has a fall-back: Simply scan the entire table (without touching any of the indexes).
If you want to discuss EXPLAINs further, please show us both the SELECT and the EXPLAIN. And show more than one pair, so we can 'compare and contrast'.
In the extra field of the explain in mysql you can get:
Using index
Using where; Using index
What's the difference between the two?
To explain my question better I'm going to use the following table:
CREATE TABLE `test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`another_field` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO test() VALUES(),(),(),(),();
Which ends up with the content like:
SELECT * FROM `test`;
id another_field
1 0
2 0
3 0
4 0
5 0
On my research I found
Why is this query using where instead of index?
The output of EXPLAIN can sometimes be misleading.
For instance, filesort has nothing to do with files, using where
does not mean you are using a WHERE clause, and using index can
show up on the tables without a single index defined.
Using where just means there is some restricting clause on the table
(WHERE or ON), and not all record will be returned. Note that
LIMIT does not count as a restricting clause (though it can be).
Using index means that all information is returned from the index,
without seeking the records in the table. This is only possible if all
fields required by the query are covered by the index.
Since you are selecting *, this is impossible. Fields other than
category_id, board_id, display and order are not covered by
the index and should be looked up.
and I also found
https://dev.mysql.com/doc/refman/5.1/en/explain-output.html#explain-extra-information
Using index
The column information is retrieved from the table using only
information in the index tree without having to do an additional seek
to read the actual row. This strategy can be used when the query uses
only columns that are part of a single index.
If the Extra column also says Using where, it means the index is being
used to perform lookups of key values. Without Using where, the
optimizer may be reading the index to avoid reading data rows but not
using it for lookups. For example, if the index is a covering index
for the query, the optimizer may scan it without using it for lookups.
For InnoDB tables that have a user-defined clustered index, that index
can be used even when Using index is absent from the Extra column.
This is the case if type is index and key is PRIMARY.
(Look at the second paragraph)
My problem with this:
First: I didn't understand the second paragraph the way it's written.
Second:
The following query returns
EXPLAIN SELECT id FROM test WHERE id = 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE test const PRIMARY PRIMARY 8 const 1 Using index
(Scroll to the right)
And this other query returns:
EXPLAIN SELECT id FROM test WHERE id > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE test range PRIMARY PRIMARY 8 NULL 1 Using where; Using index
(Scroll to the right)
Other than the fact that one query uses a range search and another uses the constant search, both queries are using some restricting clause on the table (WHERE or ON), and not all record will be returned.
What does the Using where; mean on the second query mean? and what does the fact that it's not on the first query mean?
EXTRA
What is the difference with Using index condition; Using where?
(I'm not adding an example of this because I have not been able to reproduce it in a small self contained piece os code)
When you see Using Index in the Extra part of an explain it means that the (covering) index is adequate for the query.
In your example: SELECT id FROM test WHERE id = 5; the server doesn't need to access the actual table as it can satisfy the query (you only access id) only using the index (as the explain says). In case you are not aware the PK is implemented via a unique index.
When you see Using Index; Using where it means that first the index is used to retrieve the records (an actual access to the table is not needed) and then on top of this result set the filtering of the where clause is done.
In this example: SELECT id FROM test WHERE id > 5; you still fetch for id from the index and then apply the greater than condition to filter out the records non matching the condition
I have a sql query on table with mobileno column mobileno contains "-" so in where clause i need to use replace(mobileno,"-","") function for comparision.
With explain function i checked that it doesn't use index if function is used on indexed column. So how can i force sql to used index or any other alternative to increase my query performance.
Are you sure the index is not used because of the REPLACE function? Maybe there's not enough rows to make using an index worthwhile. Or some other reason.
I ran a test with 4256 rows and to my surprise, an index was used, even with REPLACE:
EXPLAIN EXTENDED SELECT mobileno FROM test WHERE REPLACE(mobileno, '(', '') = '123) 456-789'
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE test index NULL mobileno 768 NULL 4256 100 "Using where; Using index"
EXPLAIN EXTENDED SELECT `member`.`id` , `member`.`name`
FROM `member`
WHERE `member`.`last_active` > '1289348406'
Shows the following output despite last_active having an index on it.... shouldn't it say index instead of where ?
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE member range last_active last_active 4 NULL 2 100.00 Using where
Using index means the query does not touch the table at all:
Using index
The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.
Since not all fields are covered by your index, it's impossible.
The index itself is of course being used (since the access type is range), but it still needs to do the row lookup in the table to retrieve the values of name and id.
Create a covering index on (last_active, name, id) if you want to see Using index.