我在优化以下连接多个表的查询时遇到一些问题。
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秒
使用解释:
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
我已经尝试了我能想到的一切,但似乎无法进一步优化这个查询。如有任何帮助,我们将不胜感激。
瑞克
编辑于 2015 年 3 月 22 日 @ 上午 10:27(东部时间):
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
最佳答案
有几个问题:
- 当您按
order by date_sent
使用时,date_send
上的键是使用哈希
定义的。 - 您有一个包含
brand.status
和brand.archive
的 where 子句。archive
仅存在于组合键brand_id, status, archive
中,但无法使用,因为 where 子句中未使用第一列 (brand_id)。仅为archive
创建索引,或创建复合(status, archive)
。 subject
需要自己的索引。目前,其指数深深地埋藏在综合指数中。
作为一般规则,复合索引中列的顺序很重要。仅当使用的列是第一个列时,索引才有用。此外,第一列越宽,它们的效果就越差。这意味着
KEY `snap_indx` (`snapshot_id`,`snapshot_guid`,`email`(255),`date_sent`,`subject`(255),`status`,`archive`)
效率很低,因为 subject
的 255 个字节位于 status
和 archive
之前,而 status
和 archive
各只有 4 个字节。
关于mysql - 优化mysql跨多个表的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29191077/