MySQL-任何其他索引都可以加速此查询?

时间:2018-07-07 19:10:02

标签: mysql query-optimization

我看到我的查询进行了全表扫描,并且花费了大量时间。我听说建立索引可以加快速度,并且我在表中添加了一些索引。我还应该创建其他索引来使查询速度更快吗?

我的查询是:

SELECT p.id, n.people_type_id, n.full_name, n.post, p.nick, 
p.key_name, p.email, p.internal_user_id FROM email_routing e 
JOIN people_emails p ON p.id=e.receiver_email_id 
JOIN people n ON n.id = p.people_id
WHERE e.message_id = 897360 AND e.basket=1

这是解释结果:

EXPLAIN SELECT p.id, n.people_type_id, n.full_name, n.post, p.nick, 
p.key_name, p.email, p.internal_user_id FROM email_routing e 
JOIN people_emails p ON p.id=e.receiver_email_id 
JOIN people n ON n.id = p.people_id 
WHERE e.message_id = 897360 AND e.basket=1
id select_type table partitions type possible_keys key  key_len ref         rows      filtered   Extra
1  SIMPLE      n     NULL       ALL  PRIMARY       NULL NULL    NULL        1         100.00     NULL
1  SIMPLE      p     NULL       ALL  PRIMARY       NULL NULL    NULL        3178      10.00      Using where; Using join buffer (Block Nested Loop)
1  SIMPLE      e     NULL       ref  bk1           bk1  4       server.p.id 440       1.00       Using where; Using

这是表格strucutre:

SHOW CREATE TABLE people_emails; 
CREATE TABLE `people_emails` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `nick` varchar(255) NOT NULL,
 `email` varchar(255) NOT NULL,
 `key_name` varchar(255) NOT NULL,
 `people_id` int(11) NOT NULL,
 `status` int(11) NOT NULL DEFAULT '0',
 `activity` int(11) NOT NULL,
 `internal_user_id` int(11) NOT NULL,
 PRIMARY KEY (`id`),
 FULLTEXT KEY `email` (`email`)
) ENGINE=MyISAM AUTO_INCREMENT=22114 DEFAULT CHARSET=utf8

SHOW CREATE TABLE email_routing; 
CREATE TABLE `email_routing` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `message_id` int(11) NOT NULL,
 `sender_email_id` int(11) NOT NULL,
 `receiver_email_id` int(11) NOT NULL,
 `basket` int(11) NOT NULL,
 `status` int(11) NOT NULL,
 `popup` int(11) NOT NULL DEFAULT '0',
 `tm` int(11) NOT NULL DEFAULT '0',
 KEY `id` (`id`),
 KEY `bk1` (`receiver_email_id`,`status`,`sender_email_id`,`message_id`,`basket`),
 KEY `bk2` (`sender_email_id`,`tm`)
) ENGINE=InnoDB AUTO_INCREMENT=1054618 DEFAULT CHARSET=utf8


SHOW CREATE TABLE people; 
CREATE TABLE `people` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `fname` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `lname` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `patronymic` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `gender` tinyint(1) NOT NULL,
 `full_name` varchar(255) NOT NULL DEFAULT ' ',
 `category` int(11) NOT NULL,
 `people_type_id` int(255) DEFAULT NULL,
 `tags` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `job` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `post` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `profession` varchar(255) CHARACTER SET cp1251 DEFAULT NULL,
 `zip` varchar(16) CHARACTER SET cp1251 NOT NULL,
 `country` int(11) DEFAULT NULL,
 `region` varchar(10) NOT NULL,
 `city` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `address` varchar(255) CHARACTER SET cp1251 NOT NULL,
 `address_date` date DEFAULT NULL,
 `inner` tinyint(4) NOT NULL,
 `contact_through` varchar(255) DEFAULT '',
 `next_call` date NOT NULL,
 `additional` text CHARACTER SET cp1251 NOT NULL,
 `user_id` int(11) NOT NULL,
 `changed` datetime NOT NULL,
 `status` int(11) DEFAULT NULL,
 `nick` varchar(255) DEFAULT NULL,
 `birthday` date DEFAULT NULL,
 `last_update_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 `area` text NOT NULL,
 `reviewed_` tinyint(4) NOT NULL,
 `phones_old` text NOT NULL,
 `post_sticker` text NOT NULL,
 `permissions` int(120) NOT NULL DEFAULT '0',
 `internal_user_id` int(11) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `most_used` (`category`,`status`,`city`,`lname`,`next_call`),
 KEY `registrars` (`category`,`status`,`contact_through`,`next_call`),
 FULLTEXT KEY `lname` (`lname`),
 FULLTEXT KEY `fname` (`fname`),
 FULLTEXT KEY `mname` (`patronymic`),
 FULLTEXT KEY `Full Name` (`full_name`)
) ENGINE=MyISAM AUTO_INCREMENT=415009 DEFAULT CHARSET=utf8

如何选择用于建立索引的列,我是否也应该选择文本columnts或仅适用于numer columnts

2 个答案:

答案 0 :(得分:1)

email_routing 似乎有1054618行。

然后您尝试通过message_id查找一行。

e.message_id = 897360

BUT message_id必须建立索引以加快查询速度。

message_id 是索引bk1的一部分,但这还不够,因为 message_id 不是索引的第一列。

答案 1 :(得分:0)

email_routing的需求

INDEX ( message_id, basket,  -- first, in either order
        receiver_email_id )  -- for "covering"

您的bk1 receiver_email_id开始;这不是

  1. WHERE中包括经过=测试的列。
  2. 包括WHEREGROUP BYORDER BY中的其他列(在您的情况下为无);顺序很重要,但不在讨论范围之内。
  3. 包括查询中任何地方使用的同一表的任何其他列-这是使其成为“覆盖”索引。但是,如果这会导致超过5列或涉及TEXT(不能在索引中),请不要打扰。

然后移至其他表。在两个JOINs中,似乎它们会被PRIMARY KEYsJOIN x ON x.id = ...)击中

更多讨论:Cookbook for creating indexes

关于其他问题...

您确实应该移至InnoDB。从5.6开始,它包括FULLTEXT,但是有一些differences。特别是,您可能需要更多的全文索引。例如,MATCH(lname, fname)需要FULLTEXT(lname, fname)

您真的要坚持使用cp1251吗?它将您的内部化主要限制为英语,俄语,保加利亚语,塞尔维亚语和马其顿语。尚不清楚FULLTEXT(MyISAM或InnoDB)与那些非英语语言的配合效果如何。

INTs始终为4个字节;考虑使用较小的版本。

真的只有一个people吗?优化器认为这是最好的表,但事实并非如此。我希望我在email_routing上改进的索引能使它从该表开始-绝对是最佳选择。