简体   繁体   中英

How can I make this mysql query more efficient?

I have a table for category, posts and a M2M table category_post. Here's their schema

CREATE TABLE IF NOT EXISTS `posts` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `title` char(255) COLLATE utf8_unicode_ci NOT NULL,
  `img_url` char(255) CHARACTER SET latin1 NOT NULL,
  `content` text COLLATE utf8_unicode_ci NOT NULL,
  `pub_date` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `pub_date` (`pub_date`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=42166 ;

-- --------------------------------------------------------

CREATE TABLE IF NOT EXISTS `category` (
  `c_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
  `c_name` char(255) CHARACTER SET latin1 NOT NULL,
  `c_slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `c_active` tinyint(1) NOT NULL,
  PRIMARY KEY (`c_id`),
  KEY `c_slug` (`c_slug`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='List of Categories' AUTO_INCREMENT=47 ;

-- --------------------------------------------------------

CREATE TABLE IF NOT EXISTS `category_post` (
  `cp_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `category_id` tinyint(3) unsigned NOT NULL,
  `post_id` mediumint(8) unsigned NOT NULL,
  PRIMARY KEY (`cp_id`),
  KEY `category_id` (`category_id`),
  KEY `post_id` (`post_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=60909 ;

Here's a sample query. Usually takes about 0.60 seconds and under load as high as 3 seconds.

SELECT * 
FROM posts p
INNER JOIN category_post cp ON p.id = cp.post_id
WHERE cp.category_id IN ( 10, 11, 12, 13, 15, 19, 33, 37, 46 ) 
GROUP BY id
ORDER BY pub_date DESC 
LIMIT 25690 , 10

Explain: 说明

I've been reading many references and SO posts and a bit confused about how to go about it. I'd appreciate any nod in the right direction!

I have found that if I don't include "ORDER BY pub_date DESC" the query executes in a fraction of the time. But pub_date is an index. I read somewhere that mysql will only use one index per query. Is that why it's slow?

I see that any field used in a decision context( where , join ) have an index.

I think you should replace SELECT * with SELECT to-be-used-column .

Because too many columns will slow down. However it is not basic question.

Hope that it can hope you.

The solution was to perform late row lookups. More information here . Cut down execution time from 600ms to just 90ms

Here's the updated query:

SELECT p.* 
FROM (
SELECT id
FROM posts temp
INNER JOIN category_post cp ON temp.id = cp.post_id
WHERE cp.category_id IN ( 10, 11, 12, 13, 15, 19, 33, 37, 46 ) 
GROUP BY id
ORDER BY pub_date ASC 
LIMIT 25690 , 10
) id_array
JOIN posts p ON p.id = id_array.id
ORDER BY p.pub_date ASC

Thank you everyone for your suggestions :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM