2

これは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秒かかりましたが、このようなデータベースにはまだ長すぎます

どうもありがとう

4

1 に答える 1

2

やってみました:

SELECT * FROM tbl_item 
LEFT JOIN 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

tbl_item_detailsから*を選択するだけのネストされたサブクエリは本当に必要ないと思います。テーブルを使用するだけです。

于 2012-04-11T15:40:04.013 に答える