0

誰でもこのクエリを最適化するのを手伝ってくれますか? 実行に時間がかかります:

su_pref テーブルには約 900,000 行あります

SELECT p.mykey,
       p.merchant_name,
       m.merchant_url, 
       p.name,
       p.description,
       p.image_url, 
       p.deep_link,
       p.rrp_price, 
       p.display_price, 
       c.category,
       p.su_parent_name 
FROM su_pref p #
        INNER JOIN su_categoryrefs cr ON p.mykey = cr.mykey 
        INNER JOIN su_categories c ON cr.id = c.id 
        INNER JOIN su_merchants m ON p.merchant_id=m.id 
WHERE 
     cr.id =36 
 ORDER BY p.date_created DESC LIMIT 0,20 

そして、これは EXPLAIN を使用したときに得られるものです

ここに画像の説明を入力 EXPLAIN を使用してクエリを最適化する方法を理解するのに本当に苦労しているので、どんな助けでも大歓迎です。

テーブルの定義は次のとおりです。su_pref テーブルは非常に大きいので、いくつかのフィールドを取り除きました

CREATE TABLE `su_pref` (
  `mykey` varchar(50) NOT NULL,
  `merchant_id` smallint(3) default NULL,
  `merchant_name` varchar(50) NOT NULL default '',
  `brand` varchar(50) default NULL,
  `merchantproductkey` varchar(50) default NULL,
  `upc` varchar(15) default NULL,
  `name` varchar(255) NOT NULL default '',
  `description` varchar(2500) NOT NULL default '',
  `short_description` varchar(500) default NULL,
  `thumb_url` varchar(500) default NULL,
  `image_url` varchar(500) default NULL,
  `deep_link` varchar(1000) default NULL,
  `merchant_link` varchar(255) default NULL,
  `rrp_price` decimal(11,2) default NULL,
  `display_price` decimal(11,2) default NULL,
  `delivery_cost` decimal(11,2) default NULL,
  `price_range` tinyint(1) default NULL,
  `keywords` varchar(500) default NULL,
  `su_parent_name` enum('Women','Men','') NOT NULL,
  `date_created` date default NULL,
  `date_modified` datetime default NULL,
  `wp_featured` varchar(1) default NULL,
  `hp_featured` varchar(1) default NULL,
  `published` varchar(1) default NULL,
  `in_todays_feed` varchar(1) default NULL,
  PRIMARY KEY  (`mykey`),
  KEY `merchant_id` (`merchant_id`),
  KEY `date_created` (`date_created`),
  FULLTEXT KEY `product_search` 
                (`name`,`description`,`short_description`,
                 `keywords`, `product_type`,`colour`,`style`,
                 `material`,`datafeed_category_name`,
                 `datafeed_subcategory_name`,
                 `brand`,`merchant_name`),
  FULLTEXT KEY `name` (`name`,`datafeed_category_name`, 
                       `datafeed_subcategory_name`,`product_type`,`keywords`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

-

CREATE TABLE `su_categories` (
  `id` mediumint(9) NOT NULL,
  `category` varchar(100) NOT NULL,
  `parent_id` tinyint(4) NOT NULL,
  `update_query` varchar(3000) default NULL,
  `url` varchar(150) default NULL,
  `last_update` datetime default NULL,
  PRIMARY KEY  (`id`,`category`,`parent_id`),
  KEY `parent_id` (`parent_id`),
  KEY `category_id` (`id`),
  FULLTEXT KEY `category_name` (`category`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

-

CREATE TABLE `su_categoryrefs` (
  `mykey` varchar(255) NOT NULL,
  `id` smallint(4) NOT NULL,
  PRIMARY KEY  (`mykey`,`id`),
  KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

-

CREATE TABLE `su_merchants` (
  `id` mediumint(9) NOT NULL,
  `merchant_name` varchar(40) NOT NULL,
  `merchant_url` varchar(40) default NULL,
  `merchant_website` varchar(40) default NULL,
  `merchant_description` varchar(2000) default NULL,
  `merchant_featured` varchar(1) default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `merchant_name` (`merchant_name`)
) ENGINE=MyISAM AUTO_INCREMENT=128 DEFAULT CHARSET=latin1

前もって感謝します

4

1 に答える 1

2

これらの修飾されていない各列がどのテーブルから返されているか、JOIN 述語の「merchant_id」がどのテーブルから参照されているか、または ORDER BY 句の date_created がどのテーブルから参照されているかを判断することは不可能です。(推測はできますが、あくまで推測です。

最初のステップは、実際には、これらの列参照すべてを table_name またはできればテーブル エイリアスで修飾することです。

また、単なる人間が理解できるようにステートメントをフォーマットすることは、非常に役立ちます.

修飾された列参照を使用して再フォーマットされたステートメントが役立ち、スキーマ定義を含めることも役立ちます。(回答が更新されます。)

SELECT p.mykey
     , p.merchant_name
     , merchant_url
     , `name`
     , description
     , image_url
     , deep_link
     , rrp_price
     , display_price
     , category
     , su_parent_name
 FROM su_pref p
 JOIN su_categoryrefs cr ON cr.mykey = p.mykey
 JOIN su_categories c    ON c.id     = cr.id
 JOIN su_merchants m     ON m.id     = p.merchant_id
WHERE cr.id = 36
ORDER BY date_created DESC LIMIT 0,20

一般的な経験則として、結合述語で参照される列を先行列とする索引を作成することが望ましいです。通常、これらは PRIMARY KEY とすべての外部キーです。

さらに、「カバリング インデックス」(クエリで参照されるすべての列を含むインデックス) の場合、EXPLAIN 出力に「Using index」と表示されます。これは、クエリがデータ ブロックを参照せずにインデックスから満たされていることを意味します。

EXPLAIN は、参照されている「colour_id」インデックスを示しているようですが、そのインデックスにどの列が含まれているかはまったく明らかではありません。(EXPLAIN PLAN の出力イメージは難しすぎて読めません。)


ここにいくつかの提案があります:

インデックスがあることを確認してください

ON su_categories (id, category)     -- you do
ON su_merchants (id, merchant_url)  -- never mind this one, it's a small table
ON su_categoryrefs (id, mykey)

idテーブルの列は をsu_categoryrefs参照する外部キーであり、テーブルの主キーではないと想定していsu_categories.idます。(これは と su_preferences の間の多対多の関係を解決する関係テーブルのように見えますsu_categoriesが、私は推測にすぎません。

于 2012-07-31T19:13:43.727 に答える