I have googled a lot and couldn't find a clear answer to my question
assume we have this query
SELECT * WHERE user_id = x ORDER BY date_created
If we have a single column index on user_id and another one on date_created, does the optimizer use both indexes? or just user_id index?
This is your query:
SELECT *
FROM mytable
WHERE user_id = 123
ORDER BY date_created
If you have two distinct indexes, then MySQL might use the index on user_id to apply the where predicate (if it believes that it will speed up the query, depending on the cardinality of your data, and other factor). It will not use the index on date_created, because it has no way to relate the intermediate resultset that satisfy the where predicate to that index.
For this query, you want a compound index on (user_id, date_created). The database uses the first key in the index to filter the dataset: in the index B-tree, matching rows are already sorted by date, so the order by operation becoms a no-op.
I notice that you are using select *; this is not a good practice in general, and not good for performance. If there are other columns in the table than the user and date, this forces to database to look up at the table to bring the corresponding rows after filtering and ordering through the index, which can be more expensive than not using the index at all. If you just need a few columns, then enumerate them:
SELECT date_created, first_name, last_name
FROM mytable
WHERE user_id = 123
ORDER BY date_created
And have an index on (user_id, date_created, first_name, last_name). That's a covering index: the database can execute the whole query using on the index, without looking up the table itself.
Related
I'm using partitioning RANGE BY(person_id) (10 users per sub-table) and I have these PRIMARY keys:
id,
person_id. id is a UNIQUE and auto-increment index. These indexes are holding articles that were written by person_id. If I want to retrieve all articles that were written by, lets say, person_id = 748172, I can run this query: SELECT * FROM articles WHERE person_id = 748172. But what I want to achieve, is that to be able to get older articles by running this query: SELECT * FROM articles WHERE person_id = 748172 AND id < 472785478 (or older...). Should I use composite index ALTER TABLE articles ADD INDEX '...' (person_id, id) for this case? The design of this table will be used to have up to 1 billion rows. Performance is very important here.
You should be going with NON-Clustered index when have large number of rows and performance is critical.
I have a table with 500k rows. I have specific table which takes really long time to run every query.
One of the queries is:
SELECT *
FROM player_data
WHERE `user_id` = '61120'
AND `opzak` = 'ja'
ORDER BY opzak_nummer ASC
the opzak_nummer column is a tinyint with a number.
EXPLAIN:
Is there any way to improve this query performance and the general of this query/table?
The table name is player_data and includes about 25 columns, most of them are integers with values of stats.
The index is id AUTO_INCREMENT.
You need to run that query, it will alter table and add index. You can read more details here http://dev.mysql.com/doc/refman/5.7/en/drop-index.html
ALTER TABLE pokemon_speler ADD INDEX index_name (user_id, opzak);
The optimal index for that query is either of these:
INDEX(user_id, opzak, opzak_nummer)
INDEX(opzak, user_id, opzak_nummer)
The first two columns do the filtering; the last avoids a tmp table and sort by consuming the ORDER BY.
Is any combination of columns 'unique' (other than id)? If so, we might be able to make it run even faster.
I have query that uses order-by group-by
select count(*),filed2
from table1 where field1>x group by filed2 order by count(*) desc
what are the best indexes for this query.
sholud I index filed1,field2 seprate or together?
You should create the index with both columns in two different orders
ALTER TABLE table1 ADD INDEX field1_field2_ndx (field1,field2);
ALTER TABLE table1 ADD INDEX field2_field1_ndx (field2,field1);
You should not create individual indexes because making the index with both columns will cause the query to pass through the index only to satisfy the query. It would never need to touch the table.
Even if you made individual indexes, the Query Optimizer would choose the two column index anyway.
Now that you have the two indexes, just trust the Query Optimizer to select the correct index. Based on the query, the EXPLAIN plan would choose the field2_field1_ndx index.
I have a query that looks like the following:
select count(*) from `foo` where expires_at < now()”
since expires_at is indexed, the query hits the index no problem. however the following query:
select count(*) from `foo` where expires_at < now() and some_id != 5
the index never gets hit.
both expires_at and some_id are indexed.
is my index not properly created?
This query:
SELECT COUNT(*)
FROM foo
WHERE expires_at < NOW()
can be satisfied by the index only, without referring to the table itself. You may see it from the using index in the plan.
This query:
SELECT COUNT(*)
FROM foo
WHERE expires_at < NOW()
AND some_id <> 5
needs to look into the table to find the value of some_id.
Since the table lookup is quite an expensive thing, it is more efficient to use the table scan and filter the records.
If you had a composite index on expires_at, some_id, the query would probably use the index both for ranging on expires_at and filtering on some_id.
SQL Server even offers a feature known as included fields for this. This command
CREATE INDEX ix_foo_expires__someid ON foo (expires_at) INCLUDE (some_id)
would create an index on expires_at which would additionally store some_id in the leaf entires (without overhead of sorting).
MySQL, unfortunately, does not support it.
Probably what's happening is that for the first query, the index can be used to count the rows satisfying the WHERE clause. In other words, the query would result in a table scan, but happily all the columns involved in the WHERE condition are in an index, so the index is scanned instead.
In the second query though, there's no single index that contains all the columns in the WHERE clause. So MySQL resorts to a full table scan. In the case of the first query, it was using your index, but not to find the rows to check - in the special case of a COUNT() query, it could use the index to count rows. It was doing the equivalent of a table scan, but on the index instead of the table.
1) It seems you have two single-column indices. You can try to create a multi-column index.
For a detailed explanation why this is different than multiple single column indices, see the following:
http://www.mysqlfaqs.net/mysql-faqs/Indexes/When-does-multi-column-index-come-into-use-in-MySQL
2) Do you have a B-tree index on the expires_at column? Since you are doing a range query (<), that might give better performance.
http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
Best of luck!
I have id, member_id, topic_id fields. Sometimes I use id, sometimes member_id and sometimes topic_id in WHERE clauses. Can I add Indexes to all of them? Will it make it slower? I am new to MYSQL optimization stuff, so thank you.
Unused indexes won't make a SELECT slower, but each index you add will slow down INSERTs and UPDATEs.
The maximum number of indexes a MyISAM table can have is 64
In general, you would want a separate index on each field if you will be filtering your queries only on single fields, such as in the following case:
SELECT * FROM your_table WHERE id = ?;
SELECT * FROM your_table WHERE member_id = ?;
SELECT * FROM your_table WHERE topic_id = ?;
If the id field is the primary key, then that is probably already using a clustered index. Therefore it looks like you may want to try creating two separate non-clustered indexes on member_id and topic_id:
CREATE INDEX ix_your_table_member_id ON your_table (member_id);
CREATE INDEX ix_your_table_topic_id ON your_table (topic_id);
You may also be interested in researching the topic of covering indexes.