如何删除使用临时?

1 mysql execution-plan temporary-tables

请帮助我,删除“使用临时”。我尝试了许多不同的选择,无法摆脱。或排序消失或出现“使用临时”。;(

分类表:

 `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;
Run Code Online (Sandbox Code Playgroud)

索引表:

ALTER TABLE `product_category_multi`
  ADD PRIMARY KEY (`m_Id`),
  ADD KEY `multi_cat` (`multi_cat`),
  ADD KEY `Id` (`prod_Id`);
Run Code Online (Sandbox Code Playgroud)

示例内容表:

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
Run Code Online (Sandbox Code Playgroud)

产品表:

`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;
Run Code Online (Sandbox Code Playgroud)

索引表:

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`);
Run Code Online (Sandbox Code Playgroud)

示例内容表:

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
Run Code Online (Sandbox Code Playgroud)

要求:

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)
Run Code Online (Sandbox Code Playgroud)

显示第 0 - 19 行(共 20 行,查询耗时 0.0899 秒。)

解释:

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
Run Code Online (Sandbox Code Playgroud)

这是这个变体,但它不起作用“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)
Run Code Online (Sandbox Code Playgroud)

显示第 0 - 24 行(共 2296 行,查询耗时 0.0046 秒。)

Ric*_*mes 5

临时表和文件排序不是坏事;它们是暗示索引不足的症状。

不要在JOIN什么时候使用子查询来完成这项工作:

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
Run Code Online (Sandbox Code Playgroud)

-->

SELECT prod.Id
FROM shop_product prod
INNER JOIN product_category_multi cat
    ON cat.prod_Id = prod.Id
WHERE  multi_cat = '5'
Run Code Online (Sandbox Code Playgroud)

另一方面,带有聚合的子查询 (MIN(temp.product_price) )可能比您拥有它的方式更好。

ORDER BY a DESC, b ASC无法优化。全部应为 ASC 或全部应为 DESC。在您的情况下,您订购的方式可能无关紧要id,因此请将其更改为 DESC。(可能还有其他问题阻止了此处的任何优化,但这是一个开始。)此索引可能会有所帮助: INDEX(product_warehouse_temp, product_top, product_review, Id)

如果product_category_multi是多对多映射表,则由于多种原因效率低下。 是一个更好的方法,它包含了它更好的许多原因。

在有用的地方使用“复合”索引:替换KEY multi_cat(multi_cat)(multi_cat, prod_id). 替换KEY product_article_main (product_article_main)(product_article_main, product_price)

从长远来看,InnoDB 是比 MyISAM 更好的引擎,但我现在不会强调这一点。我认为加快查询是真正的问题。

回到你的问题......目前还不清楚这个查询需要多少个“临时”表。(EXPLAIN FORMAT=JSON SELECT ...会说。)我建议的索引可能会消除一些临时表,并且可能会加快查询速度。