web-dev-qa-db-ja.com

Mysql GROUP BYは単純なビューでは本当に遅い

私はこれらのテーブルを持っています。

CREATE TABLE `movements` (
  `movementId` mediumint(8) UNSIGNED NOT NULL,
  `movementType` tinyint(3) UNSIGNED NOT NULL,
  `deleted` tinyint(1) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `movements`
  ADD PRIMARY KEY (`movementId`),
  ADD KEY `movementType` (`movementType`) USING BTREE,
  ADD KEY `deleted` (`deleted`),
  ADD KEY `movementId` (`movementId`,`deleted`);

CREATE TABLE `movements_items` (
  `movementId` mediumint(8) UNSIGNED NOT NULL,
  `itemId` mediumint(8) UNSIGNED NOT NULL,
  `qty` decimal(10,3) UNSIGNED NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `movements_items`
  ADD KEY `movementId` (`movementId`),
  ADD KEY `itemId` (`itemId`),
  ADD KEY `movementId_2` (`movementId`,`itemId`);

このビューは「movements_items_view」と呼ばれます。

SELECT 
movements_items.itemId, movements_items.qty,
movements.movementId, movements.movementType
FROM movements_items
JOIN movements ON (movements.movementId=movements_items.movementId AND movements.deleted=0)

最初のテーブルには5913行あり、2番目のテーブルには144992行があります。

ビューは非常に高速で、0.0011秒でPhpMyAdminに20結果をロードしますが、GROUP BYを要求するとすぐに(SUM()で統計を行うために必要です)es:

SELECT * FROM movements_items_view GROUP BY itemId LIMIT 0,20

時間は0.2秒以上にジャンプし、移動結合で「場所の使用;一時的な使用;ファイルソートの使用」が発生します。

編集:ビューをバイパスします。

また、phpMyAdminを介してこのクエリを実行し、ビューを使用しないようにします。

SELECT movements.movementId, movements.movementType, movements_items.qty FROM movements_items JOIN movements ON movements.movementId=movements_items.movementId GROUP BY itemId LIMIT 0,20

そして性能は基本的に同じです。

編集。これがEXPLAINです

id  select_type     table               type    possible_keys                    key            key_len     ref                        rows     Extra   
1   SIMPLE          movements           index   PRIMARY,movementid               movement_type  1           NULL                       5913     Using index; Using temporary; Using filesort
1   SIMPLE          movements_items     ref     movementId,itemId,movementId_2   movementId_2   3           movements.movementId       12       Using index

助けてくれてありがとう、ありがとう。

2
silentheaven

まず最初に:ビューをバイパスし、GROUP BYを使用して基になるクエリを実行すると、クエリの実行速度が遅くなりますか?私の経験では、MySQLはSELECTステートメント以外で使用されるビューで悪名高いです。

それで問題が解決した場合は、クエリする実際の情報を使用して(つまり、ビューにGROUP BYを含めて)2つ目のビューを作成します。

問題が解決しない場合は、改善できることがいくつかあります。

主キーを追加

movement_itemsテーブルに主キーがありません。 1つ追加します。 movementIditemIdの各組み合わせがエントリのみを持つことができる場合、それらの列からPKを複合キーにします。それ以外の場合は、代理自動インクリメント主キーを追加できます。

インデックスを追加

次のインデックスを試してください。

movement_items: (itemId,movementId,qty)

最適化したい実際のクエリを提供する

クエリの最適化は段階的なプロセスではありません。 1つのクエリを改善することはできず、その改善が関連するクエリに必ず適用されるとは期待できません。

あなたはSUMを実行したいと言っていますが、SUMクエリを表示してください。 SUMmingとは、SELECT *とは異なる最適化が必要です。

また、EXPLAINプランを提供してください。あなたはそれらを実行したと述べましたが、その非常に有用な情報を私たちに提供しないでください。

3
Willem Renzema