I have a query like below.
SELECT a,b,c,d
FROM table_name
WHERE e=1 AND f=0
GROUP BY d
ORDER BY id DESC LIMIT 5
when I indexed (e,f,d) query time : 4 sec.
when I indexed (d,e,f) query time : 20 sec.
So that I understand that index colums ordering is important.
Which index would be better for mysql?
Indexes should first satisfy the where clause, then the group or order clause. Always use EXPLAIN on your query to see how it is performed
Related
I have ProductInfo table with following indexes -
Primary: ProductCode, Model, Added_Date, id
Index: id
The composite primary key are the columns I use in the following query
SELECT * FROM ProductInfo WHERE
ProductCode='45678' AND
Model='PQA-1' AND
(Added_Date >='2021-08-01 00:00:00' AND Added_Date <='2021-08-14 23:59:59')
ORDER BY Added_Date ASC;
This query works pretty fine
Problem
The following query is fast
select * from ProductInfo WHERE ProductCode="45678" order by id desc limit 1;
Here is the explain
But the following query is very very slow. Please note that query is same but just ProductCode is different
select * from ProductInfo WHERE ProductCode="78342" order by id desc limit 1;
Here is the explain.
However, same query with Limit 2 is fast
select * from ProductInfo WHERE ProductCode="78342" order by id desc limit 2;
Here is the explain
What is the cause? Is my indexing correct? What will be the solution?
Thanks
The first query benefits from this index:
PRIMARY KEY(ProductCode, Model, Added_Date)
All the other queries could not fully benefit from either of your indexes. The Optimizer guessed at one index in one case; the other index in the other. This would work well for both cases:
INDEX(ProductCode, Id)
One reason for the timing differences is the distribution of data in the table. Your examples may not show the same timings if you change the 78342 to some other value.
The new index I recommend will make those queries "fast" regardless of the ProductCode searched on. And "Rows" will say "1" or "2" instead of about "25000".
It sounds like there are about 25K rows with ProductCode = 78342.
Following query is working like expected and uses index
Query takes 0,0481 sec
SELECT
geodb_locations.name,
geodb_locations.name_url,
COUNT(user.uid) AS useranzahl
FROM
user
LEFT JOIN
geodb_locations ON geodb_locations.id=user.plz
WHERE
user.freigeben=1 AND
geodb_locations.adm0='AT'
GROUP BY user.plz
ORDER BY useranzahl DESC
LIMIT 25
Explain
If only country locale is changed within the query from AT to DE
Query takes about 2.5 sec and does not use index
SELECT
geodb_locations.name,
geodb_locations.name_url,
COUNT(user.uid) AS useranzahl
FROM
user
LEFT JOIN
geodb_locations ON geodb_locations.id=user.plz
WHERE
user.freigeben=1 AND
geodb_locations.adm0='DE'
GROUP BY user.plz
ORDER BY useranzahl DESC
LIMIT 25
Explain
Why is index not used by the optimizer of second query and how to improve the query.
2.5 sec are to long ..
If u.uid cannot be NULL, use COUNT(*) instead of COUNT(u.uid).
As already pointed out, remove LEFT.
Add these indexes:
user: (freigeben, plz)
geodb_locations: (adm0, name_url, name)
As for why the EXPLAIN changed, ... It is quite normal (but somewhat rare) for the distribution of the constants to determine what order the tables are touched (Austria is less common than Germany?) or which index to use.
Regardless of optimizations, this query will have to scan a lot more rows for DE than for AT; this has to happen before the sort (ORDER BY) and LIMIT.
Two things prevent much optimization:
The WHERE references both tables.
The ORDER BY depends on a computed value.
id market_id date keyword sku a b c
1 1 2019-01-01 some text for this QAB-XU-VV 3.1 2.4 3.5
2 2 2019-01-02 some text for text ABC-XA-VV 2.1 4.1 1.2
3 1 2019-01-03 some text for XXX DDD-XA-RR 2.7 3.5 4.1
I need to query like this
SELECT
sku,
keyword,
SUM(a),
SUM(b),
SUM(c),
FROM A
WHERE market_id = 2 AND date BETWEEN '2020-01-01' and '2020-02-02'
GROUP BY sku, keyword
LIMIT 10
OFFSET XX
I used SampleTable(assume this table as SampleTable) and SampleTable(sku, keyword) composite-index. so this query will do index scan. query time is fast but I need to add LIMIT...OFFSET for pagination.So what I need to know is that this query will sort as SORT BY ID? I can't use ORDER BY ID since if I use this, this query will do file sort and will be very slow since it will use full scan instead of index scan. Here is what I'm confusing.
MySQL has two ways to produce ordered results: it can use a filesort,
or it can scan an index in order.
Ordering the results by the index works only when the index’s order is
exactly the same as the ORDER BY clause and all columns are sorted in
the same direction (ascending or descending).
The ORDER BY clause also has the same limitation as lookup queries: it
needs to form a leftmost prefix of the index. In all other cases,
MySQL uses a filesort.
Please help me what I'm wrong. Thank you.
WHERE, GROUP BY, and ORDER BY each want to scan the entire table.
One index may help.
In your query, INDEX(market_id, date) (or an index starting with those two columns) can avoid a full table scan and scan only part of the index. But that does nothing toward the GROUP BY or ORDER BY. Furthermore, since the WHERE clause is not all = tests, tacking on the GROUP BY columns is futile.
If you were able to get past the WHERE, then GROUP BY and ORDER BY lead to separate passes unless they are 'identical'.
I believe your query, as it stands, is doomed to need 4 passes:
Scan over index to handle the filtering by WHERE.
Sort and "group" the resulting temp table
Sort for ORDER BY.
Skip over OFFSET rows; only then can you deliver the 10 desired by LIMIT.
I have mysql db with 7 Million records
when I run query like
select * from data where cat_id=12 order by id desc limit 0,30
the query take long time like 0.4603 sec
but same query with out (where cat_id=12) or with out (order by id desc) very Fast
the query take long time like 0.0002 sec
I have indexes on cat_id and id
there is any way to make query with (where and order by) fast
thanks
Create a composite index that combines cat_id and id. See http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html for syntax and examples.
If you state 'cat_id=12' only, you will get all matching rows, which is fast, because of the index. But these rows won't be ordererd, so mysql has to read them all into a temporary table and sort that table, which is slow.
Similarly, 'order by id desc' will order the rows quickly, but mysql has to read all of them to find out which have 'cat_id=12', which is slow.
A composite index should solve these issues.
It is running fast without order by since when you write order by DESC then it first iterates through all the rows and then it selects in descending order. Removing the condition makes it by default ASCENDING which makes it fast.
Also it may be that your index is sorted ascending so when you ask for descending it needs to do a lot more work to bring it back in that order
I have an index problem with my order by statement. I have this query witch is runing fast:
SELECT name from members where kat = 2 order by date DESC;
I have a composite index on members table:
kat_index(kat,date);
Now my aplication has changed and i have added a query like this:
SELECT name from members where kat = 2 order by logged_in DESC, status DESC, date DESC;
Now the query i slow because it's using filesort. So the question is... What type of index should i add to satisfy both queries?
You should have two indexes:
(kat, date)
(kat, logged_in, status, date)
Each query will use the index that is best for that query.
You cannot cover both queries with one index. You must form a leftmost prefix on the composite index along with the ORDER BY clause as well.