我在优化连接多个表的以下查询时遇到了一些问题。
SELECT count(*) as count, `snapshot_id`, `snapshot_guid`, `image`, `subject`, `name`, `brands`.`facebook`, `brands`.`brand_id`, `brand_guid`, `date_sent`
FROM (`snapshots`)
INNER JOIN `brands` ON `snapshots`.`brand_id` = `brands`.`brand_id`
WHERE `snapshots`.`status` = 1
AND `brands`.`status` = 1
AND `brands`.`archive` = 0
GROUP BY `snapshots`.`brand_id`, `snapshots`.`subject`
ORDER BY `date_sent` desc
LIMIT 20
执行时间:4.9秒
使用EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE brands ALL PRIMARY,brand_id,status,brand_status NULL NULL NULL 338 Using where; Using temporary; Using filesort
1 SIMPLE snapshots ref brand_id,status,snapshot_brand_status snapshot_brand_status 5 mockd_catalog.brands.brand_id,const 166
描述品牌和快照表:
描述品牌
Field Type Null Key Default Extra
brand_id int(11) NO PRI NULL auto_increment
brand_guid char(12) NO MUL NULL
friendly varchar(128) YES NULL
name varchar(128) NO NULL
url varchar(2048) YES NULL
logo text YES NULL
cover text YES NULL
facebook varchar(2048) YES NULL
address_1 varchar(128) YES NULL
address_2 varchar(128) YES NULL
city varchar(50) YES NULL
state varchar(50) YES NULL
postal varchar(20) YES NULL
country_code varchar(128) YES NULL
date_created datetime YES NULL
date_modified datetime YES NULL
hp_snapshot tinyint(1) NO 0
status tinyint(1) YES MUL 0
archive tinyint(1) NO 0
描述快照
Field Type Null Key Default Extra
snapshot_id int(11) NO PRI NULL auto_increment
snapshot_guid char(36) YES MUL NULL
brand_id int(11) NO MUL 0
email varchar(256) NO MUL NULL
seed_email varchar(256) NO NULL
date_sent datetime NO MUL NULL
date_created datetime NO NULL
date_modified datetime YES NULL
content_type varchar(10) YES NULL
subject varchar(256) NO NULL
source longtext YES NULL
html longtext NO NULL
html_error text YES NULL
thumbnail text YES NULL
image text YES NULL
status tinyint(1) NO MUL 0
archive tinyint(1) NO 0
tags text YES NULL
我已经尝试了我能想到的所有内容,并且似乎无法进一步优化此查询。任何帮助表示赞赏。
瑞克
编辑3/22/2015 @ 10:27 am ET:
CREATE TABLE `snapshots` (
`snapshot_id` int(11) NOT NULL AUTO_INCREMENT,
`snapshot_guid` char(36) DEFAULT NULL,
`brand_id` int(11) NOT NULL DEFAULT '0',
`email` varchar(256) NOT NULL,
`seed_email` varchar(256) NOT NULL,
`date_sent` datetime NOT NULL,
`date_created` datetime NOT NULL,
`date_modified` datetime DEFAULT NULL,
`content_type` varchar(10) DEFAULT NULL,
`subject` varchar(256) NOT NULL,
`source` longtext,
`html` longtext NOT NULL,
`html_error` text,
`thumbnail` text,
`image` text,
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '-1= error, 0 = new, 1 = approved, 2 = review ',
`archive` tinyint(1) NOT NULL DEFAULT '0',
`tags` text,
PRIMARY KEY (`snapshot_id`),
KEY `snapshot_id` (`snapshot_id`) USING BTREE,
KEY `brand_id` (`brand_id`),
KEY `email` (`email`(255)),
KEY `status` (`status`),
KEY `snapshot_guid` (`snapshot_guid`) USING BTREE,
KEY `subject` (`subject`(255)),
KEY `archive` (`archive`),
KEY `archive_status` (`archive`,`status`),
KEY `date_sent` (`date_sent`) USING BTREE,
KEY `recent_snapshots` (`snapshot_id`,`snapshot_guid`,`archive`,`status`,`brand_id`,`date_sent`,`subject`(255)) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=95002 DEFAULT CHARSET=utf8;
品牌表:
CREATE TABLE `brands` (
`brand_id` int(11) NOT NULL AUTO_INCREMENT,
`brand_guid` char(12) NOT NULL,
`friendly` varchar(128) DEFAULT NULL,
`name` varchar(128) NOT NULL,
`url` varchar(2048) DEFAULT NULL,
`logo` text,
`cover` text,
`facebook` varchar(2048) DEFAULT NULL,
`address_1` varchar(128) DEFAULT NULL,
`address_2` varchar(128) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`state` varchar(50) DEFAULT NULL,
`postal` varchar(20) DEFAULT NULL,
`country_code` varchar(128) DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`date_modified` datetime DEFAULT NULL,
`hp_snapshot` tinyint(1) NOT NULL DEFAULT '0',
`status` tinyint(1) DEFAULT '0',
`archive` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`brand_id`),
KEY `brand_guid` (`brand_guid`) USING BTREE,
KEY `brand_id` (`brand_id`),
KEY `status` (`status`) USING BTREE,
KEY `archive_status` (`archive`,`status`),
KEY `archive` (`archive`)
) ENGINE=InnoDB AUTO_INCREMENT=423 DEFAULT CHARSET=utf8;
选择语句:
SELECT
COUNT(*) AS count,
`snapshot_id`,
`snapshot_guid`,
`image`,
`subject`,
`name`,
`brands`.`facebook`,
`brands`.`brand_id`,
`brand_guid`,
`date_sent`
FROM
(`snapshots`)
INNER JOIN
`brands` ON `snapshots`.`brand_id` = `brands`.`brand_id`
WHERE
`snapshots`.`archive` = 0
AND `snapshots`.`status` = 1
AND `brands`.`archive` = 0
AND `brands`.`status` = 1
GROUP BY `snapshots`.`brand_id` , `snapshots`.`subject`
ORDER BY `date_sent` DESC
LIMIT 20;
说明:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE snapshots ref brand_id,status,archive,archive_status status 1 const 48304 Using where; Using temporary; Using filesort
1 SIMPLE brands eq_ref PRIMARY,brand_id,status,archive_status,archive PRIMARY 4 mockd_catalog.snapshots.brand_id 1 Using where
答案 0 :(得分:0)
Ther有几个问题:
date_send
中使用using hash
时,order by date_sent
上的键定义为brand.status
。 brand.archive
和archive
的where子句。 brand_id, status, archive
仅在组合键archive
中,但由于第一列(brand_id)未在where子句中使用,因此无法使用它。仅为(status, archive)
或复合subject
创建索引。 KEY `snap_indx` (`snapshot_id`,`snapshot_guid`,`email`(255),`date_sent`,`subject`(255),`status`,`archive`)
需要一个索引。目前,其指数深埋在综合指数中。 作为一般规则,复合索引中列的顺序很重要。索引仅在使用的列是第一列时才有用。第一列越宽,它们的效果就越差。这意味着
subject
效率低,因为status
及其255个字节位于archive
和{{1}}之前,每个字节只有4个字节。