Reputation: 7765
My DB is like this: Products are N:N to Categories so there is a join table (products_categories). Products have a Supplier (1 and only 1), so Products table have a supplier_id. Products are about 500K, categories about 200 and suppliers about 80.
Right now I want to get the Distinct suppliers for Products with status = 1 and in categories 2,3 and 125.
My SQL:
SELECT DISTINCT s.id FROM suppliers s INNER JOIN
products
ASp
ON p.supplier_id = s.id INNER JOINproducts_categories
ASpc
ON p.id = pc.products_id WHERE (p.color IN ('red', 'blue')) AND pc.categories_id IN (2,3,125)
The problem with the query is the distinct. Without it the query returns in about 1 second, with DISTINCT it takes about 3 seconds. I have indexes for all FK's / PK.
Explain plan:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE pc range products_id,categories categories 4 NULL 28335 Using where; Using temporary
1 SIMPLE p eq_ref PRIMARY,color PRIMARY 4 pc.products_id 1 Using where
1 SIMPLE s eq_ref PRIMARY PRIMARY 4 p.supplier_id 1 Using where; Using index
Adding the distinct adds that "Using temporary" to the explain query plan.
So, is there any way to optimize this query? How to do this distinct in a better way (schema changes are also welcomed if needed)
Upvotes: 2
Views: 301
Reputation: 29051
Try GROUP BY
instead of DISTINCT
:
SELECT s.id
FROM suppliers s
INNER JOIN products AS p ON p.supplier_id = s.id AND p.color IN ('red', 'blue')
INNER JOIN products_categories AS pc USE INDEX (combined_index_name) ON p.id = pc.products_id AND pc.categories_id IN (2,3,125)
GROUP BY s.id
EDIT
Create a combine index on products_id
& categories_id
columns of products_categories
table. Then check the performance of query.
Upvotes: 0
Reputation: 166396
Have you tried using an EXISTS?
Something like
SELECT s.id
FROM suppliers s
WHERE EXISTS (
SELECT 1
FROM products AS p INNER JOIN
products_categories AS pc ON p.id = pc.products_id
WHERE (p.supplier_id = s.id)
AND (p.color IN ('red', 'blue'))
AND pc.categories_id IN (2,3,125)
)
Upvotes: 1