我有两张桌子。一个称为map_life
,第二个称为scripts
。 map_life
表有很多行,由名为lifeid
的列标识。表scripts
中的行由列objectid
标识。我想创建一个查询来获取表map_life
中的所有行,如果script
匹配scripts
,还会从lifeid
表中添加列objectid
,并且objecttype
为npc
。
我创建了以下查询。
SELECT id
,lifeid
,x_pos
,y_pos
,foothold
,min_click_pos
,max_click_pos
,respawn_time
,flags
,script.script
FROM map_life life
LEFT JOIN scripts script
ON script.objectid = life.lifeid
AND script.script_type = 'npc'
但是,该查询需要很多时间。我能以任何方式调整它吗?感谢。
编辑:我已经运行了EXPLAIN命令,有结果。
"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
1,"SIMPLE","life","ALL","","","","",47600,""
1,"SIMPLE","script","ref","PRIMARY","PRIMARY","1","const",1834,"Using where"
编辑2:以下是每个表的创建规范。
map_life
DROP TABLE IF EXISTS `mcdb`.`map_life`;
CREATE TABLE `mcdb`.`map_life` (
`id` bigint(21) unsigned NOT NULL AUTO_INCREMENT,
`mapid` int(11) NOT NULL,
`life_type` enum('npc','mob','reactor') NOT NULL,
`lifeid` int(11) NOT NULL,
`life_name` varchar(50) DEFAULT NULL COMMENT 'For reactors, specifies a handle so scripts may interact with them; for NPC/mob, this field is useless',
`x_pos` smallint(6) NOT NULL DEFAULT '0',
`y_pos` smallint(6) NOT NULL DEFAULT '0',
`foothold` smallint(6) NOT NULL DEFAULT '0',
`min_click_pos` smallint(6) NOT NULL DEFAULT '0',
`max_click_pos` smallint(6) NOT NULL DEFAULT '0',
`respawn_time` int(11) NOT NULL DEFAULT '0',
`flags` set('faces_left') NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`lifeid`) USING BTREE,
KEY `lifetype` (`mapid`,`life_type`)
) ENGINE=InnoDB AUTO_INCREMENT=47557 DEFAULT CHARSET=latin1;
scripts
DROP TABLE IF EXISTS `mcdb`.`scripts`;
CREATE TABLE `mcdb`.`scripts` (
`script_type` enum('npc','reactor','quest','item','map','map_enter','map_first_enter') NOT NULL,
`helper` tinyint(3) NOT NULL DEFAULT '-1' COMMENT 'Represents the quest state for quests, and the index of the script for NPCs (NPCs may have multiple scripts).',
`objectid` int(11) NOT NULL DEFAULT '0',
`script` varchar(40) NOT NULL DEFAULT '',
PRIMARY KEY (`script_type`,`helper`,`objectid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Lists all the scripts that belong to NPCs/reactors/etc. ';
答案 0 :(得分:1)
您应该根据类型向“script_type”字段添加索引。如果它没有使用可以编制索引的类型,则应尽可能更改类型并编制索引
这是一个链接,讨论有关MySQL的索引的更多信息,http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
答案 1 :(得分:1)
scripts
上的主键是:
PRIMARY KEY (`script_type`,`helper`,`objectid`)
多列密钥的顺序非常重要。
来自docs:
任何不跨越WHERE子句中所有AND级别的索引都不是 用于优化查询。换句话说,能够使用 index,必须在每个AND组中使用索引的前缀。
您在脚本上的主键确实包含script_type
和objectid
列,这两列都在加入ON
子句中使用:
ON script.objectid = life.lifeid
AND script.script_type = 'npc'
但主键还包括这两者之间的helper
列,因此MySQL只能使用主键索引进行搜索,使用第一列(script_type
)。
因此,对于每次加入,MySQL都必须搜索scripts
是' npc'的所有script_type
条记录。找到要加入的特定objectid
记录。
如果您的ON
子句包含如下所有三列,MySQL可以充分利用主键索引:
ON script.objectid = life.lifeid
AND script.helper = 1
AND script.script_type = 'npc'
如果您经常查询scripts
表而未指定helper
列,请考虑更改主键中列的顺序,以便将helper
列放在最后:
PRIMARY KEY (`script_type`,`objectid`,`helper`)
然后,您的原始ON
子句适用于索引,因为索引前缀包含谓词中的所有列(script_type
,objectid
):
ON script.objectid = life.lifeid
AND script.script_type = 'npc'
或者,添加一个仅包含ON
子句中提到的两列的附加索引:
KEY `scrypt_type_objectid` (`script_type`,`objectid`)