查询计划query plan是指优化器基于查询语句产生的,提供给服务器执行的计划内容。查看查询计划的方法是在查询语句前加上 EXPLAIN关键字。例如,以下查询要从城市表(city)和相应的国家表(country)中获得城市名称(和所属国家名称),城市表和国家表通过国家唯一代码连接。本例中仅查询了英国的字母顺序前五名的城市:
SELECT city.name AS 'City', country.name AS 'Country'FROM cityJOIN country ON (city.countrycode = country.code)WHERE country.code = 'GBR'LIMIT 5;
在查询语句前加上 EXPLAIN可以看到优化器生成的查询计划。跳过除输出末尾之外的所有内容,可以看到优化后的查询:
SELECT `world`.`city`.`Name` AS `City`, 'United Kingdom' AS `Country`FROM `world`.`city`JOIN `world`.`country`WHERE (`world`.`city`.`CountryCode` = 'GBR')LIMIT 5;
看下比较大的几个变化, country.name as 'Country'改成了'United Kingdom' AS 'Country',WHERE子句从在国家表中查找变成了在城市表中查找。优化器认为这两个改动会提供比原始查询更快的结果。
索引
在 MySQL 世界中,你会听到索引或键的概念。不过,索引是由键组成的,键是一种识别记录的方式,并且大概率是唯一的。如果将列设计为键,优化器可以搜索这些键的列表以找到所需的记录,而无需读取整个表。如果没有索引,服务器必须从第一列的第一行开始读取每一行数据。如果该列是作为唯一索引创建的,则服务器可以直接读取该行数据并忽略其余数据。索引的值(也称为基数)唯一性越强越好。请记住,我们在寻找更快获取数据的方法。
MySQL 默认的 InnoDB 存储引擎希望你的表有一个主键,并按照该键将你的数据存储在 B+ 树中。“不可见列”是 MySQL 最近添加的功能,除非在查询中明确指明该不可见列,否则不会返回该列数据。例如,SELECT * FROM foo;就不会返回任何不可见列。这个功能提供了一种向旧表添加主键的方法,且无需为了包含该新列而重写所有查询语句。
本文源于最近在 Open Source 101 会议上的一次报告。报告的演示文稿源自PHP UK Conferenc的研讨会。查询调优是一个复杂的话题,每次我就索引和直方图作报告时,我都会找到新的可改进点。但是每次报告反馈也表明很多软件界中的人并不精通索引,并且时常使用错误。我想直方图大概由于出现时间较短,还没有出现像索引这种使用错误的情况。