2017-03-18 2 views
0

おそらくデータベース設計が貧弱なため、次のような非常に単純なクエリが実行に1.5分かかります。MySQL - 大きなテーブルで多くの異なる値を持つ列別に注文する

SELECT s.title, t.name AS team_name 
    FROM stories AS s 
    JOIN teams AS t ON s.team_id = t.id 
    WHERE s.pubdate >= "1970-01-01 00:00" 
    ORDER BY s.hits /* <-- here's the problem */ 
    LIMIT 3 OFFSET 0 

問題はstories表は〜1.5メートルの列で、かなり大きいです、そしてhitsのためのユニークな値のトンがあります(この列は、各話にヒットを記録します。)

を取り出しますほぼ即座に解決されます。

質問:このようなクエリを最適化するにはどうすればよいですか?おそらく、その列に直接ルックアップがないので、hitsにインデックスを適用しないでください。

[UPDATE]関係するすべてのテーブルの

SHOW CREATE TABLE:ユーザーがそれを必要としない場合

CREATE TABLE stories (
`id` varchar(11) NOT NULL, 
`link` text NOT NULL, 
`title` varchar(255) CHARACTER SET utf8 NOT NULL, 
`description` varchar(255) CHARACTER SET utf8 DEFAULT NULL, 
`pubdate` datetime NOT NULL, 
`source_id` varchar(11) NOT NULL, 
`team_id` varchar(11) NOT NULL, 
`hits` int(11) DEFAULT NULL, 
PRIMARY KEY (`id`), 
UNIQUE KEY `Unique combo (title + date)` (`title`,`pubdate`), 
KEY `team (FK)` (`team_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

CREATE TABLE teams (
`id` varchar(11) NOT NULL, 
`is_live` enum('y') DEFAULT NULL, 
`name` varchar(50) NOT NULL, 
`short_name` varchar(12) DEFAULT NULL, 
`server` varchar(11) DEFAULT NULL, 
`url_token` varchar(255) NOT NULL, 
`league` varchar(11) NOT NULL, 
`away_game_id` varchar(255) DEFAULT NULL, 
`digest_list_id` varchar(25) DEFAULT NULL, 
`twitter_handle` varchar(255) DEFAULT NULL, 
`no_official_news` enum('y') DEFAULT NULL, 
`alt_names` varchar(255) DEFAULT NULL, 
`no_use_nickname` enum('y') DEFAULT NULL, 
`official_hashtag` varchar(30) DEFAULT NULL, 
`merge_news_and_fans` enum('y') DEFAULT NULL, 
`colour_1` varchar(6) NOT NULL, 
`colour_2` varchar(6) DEFAULT NULL, 
`colour_3` varchar(6) DEFAULT NULL, 
`link_colour_modifier` float DEFAULT NULL, 
`alt_link_colour_modifier` float DEFAULT NULL, 
`title_shade` enum('dark','light') NOT NULL, 
`shirt_style` enum('vert_stripes','horiz_stripes','vert_stripes_thin','horiz_stripes_thin','vert_split','horiz_split') DEFAULT NULL, 
PRIMARY KEY (`id`), 
KEY `URL token` (`url_token`), 
KEY `league (FK)` (`league`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 
+1

列のエイリアスを追加して、行の出現を確認します。 –

+1

'ヒットにインデックスを適用すべきではありません。なぜなら、その列で直接ルックアップが行われないからです。あなたはこれについて詳しく教えてください。私はそれを理解するのに苦労している – Sharky

+0

あなたは間違いなくインデックスを適用する必要があります。何故なの?それを試して、何が起こるかを見てください。 –

答えて

1

はpubDateの上のフィルタを削除することを検討してください。オプティマイザが混乱します。

INDEX(hits, pubdate, title) 

はおそらくクエリに最も役立ちます。それは「カバー」です。

ORDER BYを削除する理由はありません。それがなければ、のいずれかがの3行になります。それと有用なインデックスがなければ、1.5Mの行をソートしてヒット数が最も少ない3を発見する必要があります。

おそらくORDER BY s.hits DESCが必要ですか? - が最も多く、ヒットを得ることができます。

+0

ありがとう - 非常に便利です。 – Utkanos

関連する問題