Query Optimization for INNER JOIN - mysql

I have this query below:
SELECT a.id, b.item_name
FROM table_1 as a
INNER JOIN table_2 as b on a.item_id = b.item_id
There is index on a.bid as primary, and a index on a.item_id and there is an index on b.item_id as primary and index on b.item_name
However when I run the query through the EXPLAIN the primary table becomes table_1 and there is no index uses so its doing a full scan. Why wouldn't it join the index for b.item_id?

It needs to do a full scan on at least one table, as you are requesting all records. It sounds like it picked table_1. The index should be used on table_2.
If you additionally add a where clause, you can avoid that table scan. But if you actually need all rows, then a scan is the quickest way to get them.

It is doing a table scan because you ask for all rows that match. Add a WHERE a.id = <any id> and it should use the index.

Related

MySql Join tables using aggregate(min) in where condition, without subquery

I am trying to get one table, along with the lowest value of a column of another table by LEFT JOIN. I am using subquery to do this.
Sample Snippet:
SELECT *
FROM A
JOIN
(select A_id,
MIN(id) AS complete_date
from C
group by A_id) B ON (A.id=B.A_id)
WHERE A.status="complete";
Is there any possible and efficient way to achieve this without subquery and group by.
A correlated subquery -- with the right indexes -- is often the fastest approach:
SELECT A.*,
(SELECT MIN(C.id)
FROM C
WHERE A.id = C.A_id
) as complete_date
FROM A
WHERE A.status = 'complete;
This avoids the aggregation on an entire table, which is why there is a performance gain.
The index you need is on C(A_Id, id) (the second column is not as important as the first). You may also want an index on A(status).

inner join optimization after group by the subquery

so I've been working on optimize the inner join with the subquery which has group by statement. the query below it takes around 1.8 to 2 sec to fetch. I would like to optimize it and I think the subquery would be a key.
I'm not sure the subquery with group by in inner join can use index to join the other table. what I believe is that column in subquery (which is A2, C2 in this case) can not have a its own index inside inner join. is that correct?
so, my question is how can I optimize this query statement and is that possible to set index on A2, C2 in inner join.
SELECT A, C, X.S
FROM tb_g X
INNER JOIN (
SELECT A AS A2, MAX(C) AS C2
FROM tb_g
GROUP BY A
) Y
ON X.A = Y.A2 AND X.C = Y.C2;
A composite index on A, C should allow this query to be optimized as well as possible:
ALTER TABLE tb_g ADD INDEX (A, C);
This index allows the subquery to be calculated entirely with the index, and then the join with the intermediate table can be done with optimal fetching in the original table.

Possible speed up to delete via temp table in mysql

I am running a delete which removes all of the duplicates within a table. A duplicate is defined as a row where the tag_id, user_id, and is_self are all the same. My technique here is pretty standard, to preform this delete, since the tags_users table itself needs to be referenced to know if a duplicate exists a temp table is created so that a delete can be preformed from the same table that is being referenced. The problem is that this table is about a million rows so this query takes about an hour to run. I know this is related to the slow speed of defining this temp table and then referencing it as it is un-indexed.
DELETE FROM tags_users WHERE id IN (
SELECT id FROM (
SELECT A.id FROM tags_users as A, tags_users as B WHERE A.id > B.id AND A.user_id = B.user_id AND A.tag_id = B.tag_id AND A.is_self = B.is_self GROUP BY A.id
) temp_dup_delete
);
I have reviewed the explain from this query listed here (Please note I'm on mysql 5.5 so I'm using EXPLAIN SELECT 1 to simulate EXPLAIN DELETE). I think the best possible solution to this is to define an index on the temp table, but I cannot figure out how to do this yet. The crux of my question here is: is there a way to improve the speed of this query considering the way it defines a temp table. Thank you to anyone that can help.
Here is an alternative approach. Use an aggregation query to find the minimum id for each set of key values -- this seems to be the row you want to keep.
Then, use left outer join to match to this table and delete all the rows in the original data that do not match.
delete tu
from tags_users tu left outer join
(select tag_id, user_id, is_self, min(id) as minid
from tags_users
group by tag_id, user_id, is_self
) tui
on tui.id = tu.id
where tui.id is null;

MySQL Query Optimization needed

I'm trying to do a query in mysql
SELECT *
FROM table_name1
WHERE codregister IN
(SELECT register
FROM tablename2
WHERE city LIKE '%paris%')
ORDER BY date DESC
In table_name "codregister" is a primary key but in tablename2 "register" field column is a index (primary key on tablename2 is an autoincrement).
In the table_name1 doesn´t have matches with the tablename2 but the execution time of the query is to slow. Someone can recommend to improve the query?
Check this considerable difference from csf answer
SELECT *
FROM
table_a a
INNER JOIN
(SELECT register
FROM table_b
WHERE city like '%paris%') b
ON(a.codregister=b.register)
ORDER BY a.date
You're only projecting the only field of B that you need, and you are filtering B records before the join.
Use JOIN instead , and make sure joining variables are indexed .
SELECT * FROM table_name1 a
JOIN tablename2 b on a.codregister = b.register
where b.city like '%paris%'
ORDER BY a.date DESC
Also for any query you write try to use 'EXPLAIN' to find more about your query
Ref :
http://dev.mysql.com/doc/refman/5.0/en/explain.html
i agree with 0R10N Answer , filtering before join can make join faster . ThankI

Performance of query

I have an sql query to get values from 4 tables. In my query takes lot of time. I need to simplify the query
what i need is i have to display only 50 records. In my table i have 90,000 records. so i deciede to apply batch processing like
first select the 50 records from first table and then check with the 3 other tables.
if the 50 is satisfied i will display that otherwise i have to continue next 50.
But i don't have idea to implement
select file_name,
A.id,
A.reference,
user.username,
c.update_date
from A_Table A,
(select reference
from B_Table
where code = 'xxx'
group by reference
having count(*) > 1) B,
C_Table c,
D_Table d
where A.reference = B.reference
and A.id = c.id
and A.code = 'ICG'
and c.updated_by = d.user_id
order by 3
limit 20;
The query looks fine.
Adding some indexes will help a lot.
Assuming the id columns (A_Table.id and C_Table.id) are already PRIMARY KEY columns, you won't need to index them.
ALTER TABLE A_Table
ADD INDEX (reference),
ADD INDEX (code);
ALTER TABLE B_Table
ADD INDEX (reference),
ADD INDEX (code, reference);
ALTER TABLE C_Table
ADD INDEX (updated_by);
ALTER TABLE D_Table
ADD INDEX (user_id);