Speed up search query (large junction table)
-
11-02-2021 - |
Question
I'm writing a multistore webshop application in PHP/MYSQL. The products table has about a million records, currently i'm having 5 stores with all products in it and about 3 stores with a few products. The product's price sometimes varies from store to store. Because it should be possible to add or delete certain products for let's say only shop 2, i created a junction table. My tables looks like this:
products(id,name,description,price,media) ~1M records
stores(id,name)
products_stores(id,product_id,store_id,price) ~5M records
When searching for products the query takes about 20 seconds. I added indices to products(name,description) + products_stores(product_id,store_id). Is there any way I could speed up the process? Most of the records in products_stores are the same (except for the store_id), but I'd like to keep it flexible.
The query:
SELECT
Product.id,
Product.name,
Product.drager,
Product.import,
Product.price,
Product.description,
Product.units
FROM
products AS Product
INNER JOIN
products_stores AS ProductStore ON (
ProductStore.product_id = Product.id
AND
ProductStore.store_id =1
)
WHERE
name LIKE 'bach%'
ORDER BY
Product.description asc
LIMIT
500
I added a FULLTEXT index on only name and deleted the ORDER BY statement, but it seems to make no difference. My indices are now:
Products(name) BTREE
Products(name,description) FULLTEXT
Products(name) FULLTEXT
EXPLAIN of the above query gives: (with indices) http://i.stack.imgur.com/8Fe8C.gif
Thanks in advance and sorry for my bad English.
Solution
read the following links about clustered primary keys:
http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html
http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/
MySQL and NoSQL: Help me to choose the right one
Any way to achieve fulltext-like search on InnoDB
How to avoid "Using temporary" in many-to-many queries?
60 million entries, select entries from a certain month. How to optimize database?
then redesign your product_stores table something along the lines of:
create table products_stores
(
store_id int unsigned not null,
product_id int unsigned not null,
...
primary key (store_id, product_id)
)
engine=innodb;
hope this helps :)
OTHER TIPS
Because you are looking for products from a specific store, I would have an index on the store ID AND the Name, then adjust the query to pre-qualify the products FROM the given store instead of looking at all products first.
SELECT STRAIGHT_JOIN
P.id,
P.name,
P.drager,
P.import,
P.price,
P.description,
P.units
FROM
Product_Stores PS
JOIN Products P
on PS.Product_ID = P.ID
AND P.Name like 'back%'
WHERE
PS.Store_ID = 1
order by
P.Description
limit
500