「一時的な使用」を削除してください。私は多くの異なるオプションを試しましたが、取り除くことは不可能です。または、ソートが消えるか、「一時使用中」と表示されます。 ;(
カテゴリテーブル:
`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;
インデックステーブル:
ALTER TABLE `product_category_multi`
ADD PRIMARY KEY (`m_Id`),
ADD KEY `multi_cat` (`multi_cat`),
ADD KEY `Id` (`prod_Id`);
コンテンツテーブルの例:
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
製品表:
`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;
インデックステーブル:
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`);
コンテンツテーブルの例:
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
リクエスト:
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)
行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
これはこのバリアントでしたが、「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)
行0〜24を表示しています(合計2296、クエリにかかった時間は0.0046秒です)。
Tempテーブルとfilesortは悪ではありません。それらは不十分なインデックスを暗示する症状です。
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
_
->
_SELECT prod.Id
FROM shop_product prod
INNER JOIN product_category_multi cat
ON cat.prod_Id = prod.Id
WHERE multi_cat = '5'
_
一方、集計(MIN(temp.product_price)
)を使用したサブクエリは、おそらくそれよりも優れています。
_ORDER BY a DESC, b ASC
_は最適化できません。すべてASCまたはDESCである必要があります。あなたの場合、id
を注文する方法はおそらく問題ではないので、DESCに変更します。 (ここでの最適化を妨げる他の問題があるかもしれませんが、これは始まりです。)このインデックスmightヘルプ: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よりも優れたエンジンですが、現時点ではそれについては触れません。クエリの高速化はrealの質問だと思います。
質問に戻りましょう...このクエリに必要な「一時」テーブルの数は不明です。 (_EXPLAIN FORMAT=JSON SELECT ...
_と表示されます。)私の推奨インデックスmayは一時テーブルの一部を削除し、おそらくクエリを高速化します。