Tell me, please, how to get rid of Using Temporary and that the request would work as fast as possible while

Category table:

`product_category_multi` ( `m_Id` mediumint(7) NOT NULL, `prod_Id` smallint(6) unsigned NOT NULL, `multi_cat` mediumint(7) unsigned NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

Indices:

 ALTER TABLE `product_category_multi` ADD PRIMARY KEY (`m_Id`), ADD KEY `multi_cat` (`multi_cat`), ADD KEY `Id` (`prod_Id`); 

inside view:

 m_Id prod_Id multi_cat -------+-----------+---------+ 1 1 5 2 1 1 3 1 6 4 2 5 5 2 1 6 3 5 7 4 5 8 4 6 

Tables with the goods:

 `shop_product` ( `Id` int(10) unsigned NOT NULL, `product_article` varchar(20) NOT NULL, `product_article_main` varchar(20) NOT NULL, `product_category` int(10) unsigned NOT NULL DEFAULT '0', `product_name` varchar(255) NOT NULL, `product_price` int(10) unsigned NOT NULL DEFAULT '0', `product_active` smallint(1) unsigned NOT NULL DEFAULT '0', `product_warehouse_temp` enum('0','1') NOT NULL, `product_top` enum('0','1') NOT NULL, ) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0; 

Indices:

 ALTER TABLE `shop_product` ADD PRIMARY KEY (`Id`), ADD KEY `product_name` (`product_name`), ADD KEY `product_price` (`product_price`), ADD KEY `product_article_main` (`product_article_main`); 

Inside view:

 Id product_article product_article_main product_category product_name product_price product_active product_warehouse_temp product_top --+-------------------+------------------------+------------------+---------------+----------------+--------------+------------------------+------------+ 1 qwe qwe 5 name1 20 1 1 0 2 asd qwe 5 name2 30 1 1 0 3 zxc qwe 5 name3 50 1 0 1 4 wer sdf 6 name4 10 1 1 0 5 sdf sdf 6 name5 20 1 1 0 6 xcv sdf 6 name6 50 1 1 0 7 ert cvb 1 name7 10 1 0 1 8 cvb cvb 1 name8 20 1 1 0 

Option 1 request with Using temporary:

 SELECT A.* FROM ( SELECT prod.Id FROM shop_product prod INNER JOIN ( SELECT prod_Id FROM product_category_multi WHERE multi_cat = '5' ) AS cat ON cat.prod_Id = prod.Id WHERE prod.product_active = '1' AND prod.product_published_start <= 1471376797 AND prod.product_price = ( select MIN(temp.product_price) from shop_product temp where prod.product_article_main=temp.product_article_main ) ORDER BY prod.product_warehouse_temp DESC, prod.product_top DESC, prod.product_review DESC, prod.Id ASC LIMIT 0, 20 ) B INNER JOIN shop_product A USING (Id) 

Showing rows 0 - 19 (20 total, Query took 0.0899 seconds.)

EXPLAIN:

 id select_type table type possible_keys key key_len ref rows Extra --+---------------+------------------------+-----------+----------------------+-----------------------+-----------+-------------------------------+--------+------------- 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20 1 PRIMARY A eq_ref PRIMARY PRIMARY 4 B.Id 1 2 DERIVED product_category_multi ref multi_cat,Id multi_cat 3 const 6869 Using temporary; Using filesort 2 DERIVED prod eq_ref PRIMARY PRIMARY 4 product_category_multi.prod_Id 1 Using index condition; Using where 4 DEP. SUBQUERY temp ref product_article_main product_article_main 62 prod.product_article_main 3 

Option 2, works quickly, without Using temporary but does not work ORDER BY

  SELECT B.* FROM( SELECT prod_Id FROM product_category_multi WHERE multi_cat = '5' ) cat INNER JOIN ( SELECT prod.Id FROM shop_product prod WHERE prod.product_price = ( select MIN(temp.product_price) from shop_product temp where prod.product_article_main=temp.product_article_main ) AND prod.product_active = '1' AND prod.product_published_start <= '1471268208' ORDER BY prod.product_warehouse_temp DESC, prod.product_top DESC ) prod ON cat.prod_Id = prod.id INNER JOIN shop_product B USING (Id) 

Showing rows 0 - 24 (2296 total, Query took 0.0046 seconds.)

  • And why do you have ORDER BY in subqueries, and not in an external query? - cheops
  • @cheops In the second option, yes, but it does not work. In the first version of ORDER BY in an external query, but gives Using temporary - klerol
  • This temporary using was given to you. your select min () subquery is executed 6 thousand times. And it does not bother you? I would be strained and I would think about some kind of join with a subquery returning all the necessary minimums in one pass. although of course the total number of records in the table should be looked at. - Mike

0