私はこれらのテーブルを持っています。
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
助けてくれてありがとう、ありがとう。
まず最初に:ビューをバイパスし、GROUP BY
を使用して基になるクエリを実行すると、クエリの実行速度が遅くなりますか?私の経験では、MySQLはSELECT
ステートメント以外で使用されるビューで悪名高いです。
それで問題が解決した場合は、クエリする実際の情報を使用して(つまり、ビューにGROUP BY
を含めて)2つ目のビューを作成します。
問題が解決しない場合は、改善できることがいくつかあります。
movement_items
テーブルに主キーがありません。 1つ追加します。 movementId
とitemId
の各組み合わせがエントリのみを持つことができる場合、それらの列からPKを複合キーにします。それ以外の場合は、代理自動インクリメント主キーを追加できます。
次のインデックスを試してください。
movement_items: (itemId,movementId,qty)
クエリの最適化は段階的なプロセスではありません。 1つのクエリを改善することはできず、その改善が関連するクエリに必ず適用されるとは期待できません。
あなたはSUM
を実行したいと言っていますが、SUM
クエリを表示してください。 SUM
mingとは、SELECT *
とは異なる最適化が必要です。
また、EXPLAIN
プランを提供してください。あなたはそれらを実行したと述べましたが、その非常に有用な情報を私たちに提供しないでください。