Reputation: 47
I'm working on a query that needs to connect 4 large tables.
The tables:
Table_1 (ID, active, price1, price2, name, category1, category2) This is the main table that has all the products, 32561 rows
table_2 (ID, table_1_ID, room, stock) This is the table that contains the stock of the products in table_1, this table can have table_1.ID multiple times, 190400 rows
table_3 (ID, table_1_ID, images) This table contains more info about a product like images, some products don't have them, 6546 rows
table_4 (table_1_ID, view, type) This table contains views of products (views per month)
What i want:
I'm trying to make a query that displays 20 of the top viewed products.
Conditions:
The code:
SELECT DISTINCT(Table_1.ID), Table_1.price1, Table_1.price2
, Table_1.name, Table_1.category2, Table_3.images
FROM Table_1
LEFT JOIN Table_2 ON Table_1.ID=Table_2.table_1_ID
LEFT JOIN table_3 ON table_1.ID=table_3.table_1_ID
LEFT JOIN table_4 ON table_1.ID=table_4.table_1_ID
WHERE Table_1.active='T'
AND (Table_1.category1 LIKE 'A%'
OR Table_1.category1 LIKE 'B%'
OR Table_1.category1 LIKE 'C%'
OR Table_1.category1 LIKE 'D%'
OR Table_1.category1 LIKE 'E%'
)
AND table_2.room IN ('LJ0001','MS0001')
AND table_2.stock!=0
ORDER BY table_4.view DESC, Table_1.name
LIMIT 10 OFFSET 0
Note:
The code above works. But it take a while. I'm looking for any fixes that could make this faster.
Any help would be nice! Thanks in advance.
EXPLAIN EXTENDED
Upvotes: 1
Views: 93
Reputation: 651
I think my fixes can help you. if you can set sql_cache_type = 2 in my.cnf you should use SQL_CACHE in query (if there are not fields with text type) and it is better first do conditions which are "easier" for DB (LIKE with OR are very slow), if you use INNODB you can set a larger buffer pool for MySQL
SELECT SQL_CACHE DISTINCT(Table_1.ID), Table_1.price1, Table_1.price2
, Table_1.name, Table_1.category2, Table_3.images
FROM Table_1
LEFT JOIN Table_2 ON Table_1.ID=Table_2.table_1_ID
LEFT JOIN table_3 ON table_1.ID=table_3.table_1_ID
LEFT JOIN table_4 ON table_1.ID=table_4.table_1_ID
WHERE Table_1.active='T'
AND table_2.stock!=0
AND table_2.room IN ('LJ0001','MS0001')
AND (Table_1.category1 LIKE 'A%'
OR Table_1.category1 LIKE 'B%'
OR Table_1.category1 LIKE 'C%'
OR Table_1.category1 LIKE 'D%'
OR Table_1.category1 LIKE 'E%'
)
ORDER BY table_4.view DESC, Table_1.name
LIMIT 10 OFFSET 0
Upvotes: 0
Reputation: 394
Use the updated query below:
EXPLAIN EXTENDED
SELECT Table_1.ID, Table_1.price1, Table_1.price2
, Table_1.name, Table_1.category2, Table_3.images
FROM Table_1
LEFT JOIN Table_2 ON Table_1.ID=Table_2.table_1_ID
LEFT JOIN table_3 ON table_1.ID=table_3.table_1_ID
LEFT JOIN table_4 ON table_1.ID=table_4.table_1_ID
WHERE Table_1.active='T'
AND (Table_1.category1 = 'A'
OR Table_1.category1 = 'B'
OR Table_1.category1 = 'C'
OR Table_1.category1 = 'D'
OR Table_1.category1 = 'E'
)
AND table_2.room IN ('LJ0001','MS0001')
AND table_2.stock != 0
ORDER BY table_4.view DESC, Table_1.name
LIMIT 10 OFFSET 0
I deleted DISTINCT
because I assumed that table_1.ID
is a primary key. If so,there is no need to use DISTINCT
with primary keys because it's already distinct. I also changed the LIKE
operator to =
it because it works faster.
Then you need to make sure that all join fields such as table_1_ID
have been indexed.
And you may notice EXPLAIN EXTENDED
on the top of the query - with this clause you will get something like this from the db:
id: 1
select_type: PRIMARY
table: t1
type: index
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
rows: 4
filtered: 100.00
Extra: Using index
You will get the description for each table. All foreign keys used in the query will be listed, including details like if the foreign key has index, etc. You will find more info here.
Upvotes: 1