3

いくつかのクエリでいくつかの実際の問題がありますが、これは特に問題です。以下の情報。

tgmp_games、約2万行

CREATE TABLE IF NOT EXISTS `tgmp_games` (
  `g_id` int(8) NOT NULL AUTO_INCREMENT,
  `site_id` int(6) NOT NULL,
  `g_name` varchar(255) NOT NULL,
  `g_link` varchar(255) NOT NULL,
  `g_url` varchar(255) NOT NULL,
  `g_platforms` varchar(128) NOT NULL,
  `g_added` datetime NOT NULL,
  `g_cover` varchar(255) NOT NULL,
  `g_impressions` int(8) NOT NULL,
  PRIMARY KEY (`g_id`),
  KEY `g_platforms` (`g_platforms`),
  KEY `site_id` (`site_id`),
  KEY `g_link` (`g_link`),
  KEY `g_release` (`g_release`),
  KEY `g_genre` (`g_genre`),
  KEY `g_name` (`g_name`),
  KEY `g_impressions` (`g_impressions`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

tgmp_reviews-約20万行

CREATE TABLE IF NOT EXISTS `tgmp_reviews` (
  `r_id` int(8) NOT NULL AUTO_INCREMENT,
  `site_id` int(6) NOT NULL,
  `r_source` varchar(128) NOT NULL,
  `r_date` date NOT NULL,
  `r_score` int(3) NOT NULL,
  `r_copy` text NOT NULL,
  `r_link` text NOT NULL,
  `r_int_link` text NOT NULL,
  `r_parent` int(8) NOT NULL,
  `r_platform` varchar(12) NOT NULL,
  `r_impressions` int(8) NOT NULL,
  PRIMARY KEY (`r_id`),
  KEY `site_id` (`site_id`),
  KEY `r_parent` (`r_parent`),
  KEY `r_platform` (`r_platform`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 ;

これがクエリです。3秒かかります。

SELECT * FROM tgmp_games g
RIGHT JOIN tgmp_reviews r ON g_id = r.r_parent
WHERE g.site_id = '34'
GROUP BY g_name
ORDER BY g_impressions DESC LIMIT 15

説明

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE  r   ALL     r_parent    NULL    NULL    NULL    201133  Using temporary; Using filesort
1   SIMPLE  g   eq_ref  PRIMARY,site_id     PRIMARY     4   engine_comp.r.r_parent  1   Using where

私は、最も視聴された15のゲームを取得しようとしています。次に、各ゲームについて1つのレビュー(どちらが理想的であるかは重要ではありません、r_score)を取得します。

誰かが私がこれがとてもひどく非効率的である理由を理解するのを手伝ってもらえますか?

4

2 に答える 2

2
  1. クエリにを含める目的がわかりませんGROUP BY g_nameが、これにより、MySQLは、選択された列、または両方のテーブルのすべての列に対して集計を実行します。したがって、それを除外して、それが役立つかどうかを確認してください。

  2. また、RIGHT JOINデータベースをtgmp_reviews最初にクエリするようにしますが、これは必要なことではありません。LEFT JOINここではより良い選択だと思います。結合タイプを変更してみてください。

  3. 最初のオプションのいずれも役に立たない場合は、クエリを再設計する必要があります。このサイトで最も視聴されている15のゲームを入手する必要があるため、クエリは次のようになります。

    SELECT g_id
      FROM tgmp_games g
     WHERE site_id = 34
     ORDER BY g_impressions DESC
     LIMIT 15;
    

    これは、最高の選択性を提供するため、データベースによって実行される必要がある最初の部分です。次に、ゲームに必要なレビューを取得できます。

    SELECT r_parent, max(r_score)
      FROM tgmp_reviews r
     WHERE r_parent IN (/*1st query*/)
     GROUP BY r_parent;
    

    このような構成により、データベースは最初のクエリを最初に実行し(トートロジーについては申し訳ありません)、必要な各ゲームの最大スコアを取得します。得られた結果をご利用いただければ幸いです。

于 2012-08-09T20:04:45.947 に答える
1

MyISAMテーブルは小さいので、変換して問題が解決するかどうかを確認できます。そのテーブルにInnoDBの代わりにMyISAMを使用する理由はありますか?

また、各テーブルで分析を実行して統計を更新し、オプティマイザーが別のものを選択するかどうかを確認することもできます。

于 2012-08-09T17:15:32.157 に答える