How to improve IF NOT NULL query? - mysql

I have the following query:
SELECT * FROM `title_mediaasset`
WHERE upload_id is not null
ORDER BY `upload_date` DESC
It takes almost a second and doesn't use an index:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE title_mediaasset ALL upload_id,upload_id_2 NULL NULL NULL 119216 Using where; Using filesort
How can I improve this query?
This table holds about 100k results, and will probably increase to 1M in the next year.

If you need all rows and all columns from the result, you can't re-write the query to make it better. It is probably running slow because you don't have an index on upload_date.
If you don't need all of the rows, use LIMIT and you'll see a decent speed increase on the ORDER BY.
If you don't need all of the columns, use SELECT [columns you need] instead of SELECT *. That way if you really need to optimize the query, you can put the columns you need in your index so that you can read everything directly from the index: index on (upload_id, upload_date, [other columns in select statement]).
If you need all of the columns, or a good number of them, just add index on (upload_id, upload_date).

Related

Why this simple query not using any one index?

Query:
SELECT *, history_count as `count`
FROM pdf_history
WHERE 1 AND history_date>=1426180929 AND history_count!=0
EXPLAIN
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE pdf_history ALL history_date,history_count NULL NULL NULL 697 Using where
One of the reason optimizer choose not to use the index is when the filter doesn't reduce the search space.
for example if
history_date>=1426180929
or
history_count!=0
already bring all the records then using the index doesnt really help.
My suggestion do this both querys and check the ANALYZEto see how many of the
600 records are match that filter
SELECT count(*) FROM pdf_history WHERE history_date>=1426180929;
SELECT count(*) FROM pdf_history WHERE history_count!=0;

MySQL COUNT takes 11s, how to improve

I am trying to count the occurrence of sales.
Here is my query:
SELECT item, COUNT(item) FROM sales_raw
GROUP BY item HAVING (count(item)>=1)
ORDER BY COUNT(item) DESC
This query takes about eleven seconds on a table of about 500,000 rows. When I do an explain, I get:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE sales_raw index NULL vendor_id 767 NULL 397431 Using temporary; Using filesort
Why does this query take so long and how can I improve this?
Replace every COUNT(item) by COUNT(*). The former checks if values in item are NULL, and not the latter.
If it is still not fast enough, add an index on your item column, which should make your query significantly faster.
Also, the HAVING clause seems useless as COUNT(item) cannot return 0, since the item wouldn't be in the table in the first place.

mysql performance issues

i have a simple query with no joins that is running very slow (20s+). The table queried has about 400k rows and all columns used in the where clause are indexed.
SELECT deals.id, deals.title,
deals.amount_sold * deals.sale_price AS total_sold_total
FROM deals
WHERE deals.country_id = 33
AND deals.target_approved = 1
AND deals.target_active = 1
AND deals.finished_at >= '2012-04-01'
AND deals.started_at <= '2012-04-30'
ORDER BY total_sold_total DESC
LIMIT 0, 10
Im struggling with this since last week, please i could use some help :)
Update 1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE deals index_merge NewIndex3,finished_at_index,index_deals_on_country_id,index_deals_on_target_active,index_deals_on_target_approved index_deals_on_target_active,index_deals_on_target_approved,index_deals_on_country_id 2,2,5 \N 32382 Using intersect(index_deals_on_target_active,index_deals_on_target_approved,index_deals_on_country_id); Using where; Using filesort
To improve the selection, create the following compound indexes, using the columns in the WHERE clause, in the order specified:
(country_id, target_approved, target_active, finished_at)
(country_id, target_approved, target_active, started_at)
You want columns with higher cardinality first, with ranges last. MySQL cannot utilize any key parts past the first range, which is why we have two separate indexes that diverge at the range in the WHERE clause (>= and <=).
If MySQL doesn't utilize both indexes through an index merge, then you might consider deleting one of them.
Unfortunately, MySQL still has to return all of the rows, computing the total_sold_total, before it can order the rows. In other words, MySQL has to manually sort the rows after it has retrieved the entire dataset.
The time it takes to sort will be directly proportional to the size of the result set.
LIMIT optimizations cannot be used because LIMIT is applied after the sort.
Unfortunately, having ranges in your WHERE clause precludes you from adding a precalculated total_sold_total column to the end of your index to return the results already in order, which would prevent the manual sort.

How is using Join faster than using just Rand() in MySQL

How is
SELECT t.id
FROM table t
JOIN (SELECT(FLOOR(max(id) * rand())) AS maxid FROM table)
AS tt
ON t.id >= tt.maxid
LIMIT 1
faster than
SELECT * FROM `table` ORDER BY RAND() LIMIT 1
I am actually having trouble understanding the first. Maybe if I knew why one is faster than the other I would have a better understanding.
*original post # Difficult MySQL self-join please explain
You can use EXPLAIN on the queries, but basically:
In the first you're getting a random number (which isn't very slow), based on the maximum of a (i presume) indexed field. This is quite quick, i'd say maybe even near-constant time (depends on the implementation of the index hash?)
Then you're joining on that number and returning only the first row that's greater then, and because you're using an index again, this is lightning quick.
The second is ordering by some random function. This has to, but you'll need to look at the explain for that, do a FULL TABLE scan, and then return the first. This is ofcourse VERY expensive. You're not using any indexes because of that rand.
(the explain will look like this, showing that you're not using keys)
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE table ALL NULL NULL NULL NULL 14 Using temporary; Using filesort

Why is this query using where instead of index?

EXPLAIN EXTENDED SELECT `board` . *
FROM `board`
WHERE `board`.`category_id` = '5'
AND `board`.`board_id` = '0'
AND `board`.`display` = '1'
ORDER BY `board`.`order` ASC
The output of the above query is
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE board ref category_id_2 category_id_2 9 const,const,const 4 100.00 Using where
I'm a little confused by this because I have an index that contains the columns that I'm using in the same order they're used in the query...:
category_id_2 BTREE No No
category_id 33 A
board_id 33 A
display 33 A
order 66 A
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.
It is actually using index category_id_2.
It's using the index category_id_2 properly, as shown by the key field of the EXPLAIN.
Using where just means that you're selecting only some rows by using the WHERE statement, so you won't get the entire table back ;)