これはstackoverflowでの私の最初の質問であり、通常はインターネットで回答を検索することに慣れていますが、今回はこの質問に対する回答が見つかりませんでした。
単純に私の問題は、2つのテーブル間の単純な結合であるのに、クエリの実行に時間がかかりすぎることです。
最初にクエリを投稿してから、システムに関する詳細を投稿します。
SELECT * FROM tbl_item
LEFT JOIN (SELECT * FROM tbl_item_details) AS tbl_item_details
ON tbl_item.item_id = tbl_item_details.item_details_item_id
WHERE item_active = 1 ORDER BY item_views DESC LIMIT 0,5
これが私のテーブル構造です:
CREATE TABLE `tbl_item` (
`item_id` int(11) NOT NULL AUTO_INCREMENT,
`item_views` int(11) NOT NULL,
`item_active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`item_id`)
) ENGINE=InnoDB AUTO_INCREMENT=821 DEFAULT CHARSET=utf8
tbl_item_details:
CREATE TABLE `tbl_item_details` (
`item_details_id` int(11) NOT NULL AUTO_INCREMENT,
`item_details_title` varchar(255) NOT NULL,
`item_details_content` longtext NOT NULL,
`item_details_item_id` int(11) NOT NULL,
PRIMARY KEY (`item_details_id`),
KEY `itm_dt_itm_id` (`item_details_item_id`),
CONSTRAINT `tbl_item_details_ibfk_1` FOREIGN KEY (`itm_dt_itm_id`) REFERENCES `tbl_item` (`itm_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=364 DEFAULT CHARSET=utf8
EXPLAINクエリの出力は次のとおりです。
idselect_typeテーブルタイプpossible_keyskeykey_len ref rows Extra 1 PRIMARY tbl_item ALL NULL NULL NULL NULL358whereの使用; 一時的な使用; filesortの使用 1 PRIMARY ALL NULL NULL NULL NULL 358 2派生tbl_item_detailsALLNULL NULL NULL NULL 422
各テーブルには350行しかなく、大きなテーブル(tbl_item_details)は1.5 MBなので、テーブルはかなり小さいことがわかります。
基本的に、上記のクエリは、次のシステムで実行するのに約4秒かかります。
CPU:Intel(R)Pentium(R)4 CPU 3.20GHz(2 CPU)、〜3.2GHz RAM:3 GB Mysql:5.1.33(wampに含まれる)
前に、誰かがここでの解決策は私が試したもの、うまくいったもの、うまくいかなかったものだと提案します:
うまくいき、クエリにかかる時間ははるかに短くなりました(0.06秒)。
- ORDERBYを削除してみましたitem_details_contentを削除してみました
- 代わりにINNERJOINを使用して試した選択で、うまくいきました
- 結合内のテーブルを切り替えて、INNERテーブルがOUTERになり、その逆も同様になります。
tbl_item_detailsに一致しない行がtbl_itemにある可能性があり、これらのレコードが必要なため、INNERJOINを使用できません。
私が試したものでうまくいかなかったもの:
- item_viewsにインデックスを追加してみました(機能しませんでした)
- 外部キー制約を削除してみました
- テーブルエンジンをMyIsamにウィッチしてみました
明らかに、mysqlがitem_details_content内の日付と面(比較的)の大きなデータを並べ替えているときに問題が発生するため、いずれか(並べ替えまたは列item_details_content)を削除すると、問題なく機能します。
しかし、問題は、これは起こらないはずです!cosテーブルには、合計1.5 MBの350行しかないことを考えると、非常に小さなデータが含まれています。mysqlはそれよりもはるかに多くのデータを処理できるはずです。
クエリ構造の大幅な変更を提案する前に、私はこのフレームワークにしばらく取り組んでおり、クエリが動的に生成され、クエリの変更は数日間の作業を意味する可能性があるため、それは不可能です。あなたの提案はいつでも大歓迎です。
PS:強力なサーバー(コアi7と8 GB RAM)でこのクエリを試しましたが、0.3秒かかりましたが、このようなデータベースにはまだ長すぎます
どうもありがとう