使MySQL使用索引/键,其中1列,其中where和2依次由

|| 如何让MySQL使用具有以下表结构和查询的键/索引?
-- the table
CREATE TABLE `country` (
  `id` int(11) NOT NULL auto_increment,
  `expiry_date` datetime NOT NULL,
  `name` varchar(50) collate utf8_unicode_ci NOT NULL,
  `symbol` varchar(5) collate utf8_unicode_ci NOT NULL,
  `exchange_rate` decimal(11,5) NOT NULL default \'1.00000\',
  `code` char(3) collate utf8_unicode_ci NOT NULL,
  `currency_code` varchar(3) collate utf8_unicode_ci NOT NULL,
  `display_order` smallint(6) unsigned NOT NULL default \'0\',
  PRIMARY KEY  (`id`),
  KEY `code` (`code`),
  KEY `currency_code` (`currency_code`),
  KEY `display_order` (`expiry_date`,`name`,`display_order`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- the query
SELECT `country`.* 
FROM `country` 
WHERE `country`.`expiry_date` = 0 
ORDER BY `country`.`display_order` ASC, `country`.`name` ASC;
我正在尝试使其使用键,因为结果中包含180的查询需要0.0013s,并且是该页面上最慢的查询(比下一个最慢的查询长3倍)。据我了解,查询应使用“ 1”索引/键。
已邀请:
更改为:
CREATE TABLE `country` (
  `id` int(11) NOT NULL auto_increment,
  `expiry_date` datetime NOT NULL,
  `name` varchar(50) collate utf8_unicode_ci NOT NULL,
  `symbol` varchar(5) collate utf8_unicode_ci NOT NULL,
  `exchange_rate` decimal(11,5) NOT NULL default \'1.00000\',
  `code` char(3) collate utf8_unicode_ci NOT NULL,
  `currency_code` varchar(3) collate utf8_unicode_ci NOT NULL,
  `display_order` smallint(6) unsigned NOT NULL default \'0\',
  PRIMARY KEY  (`id`),
  KEY `code` (`code`),
  KEY `currency_code` (`currency_code`),
  KEY `expiry` (`expiry_date`,`name`,`display_order`) <<- renamed key for clarity
  /* always name compound keys for their left-most parts*/ 
  KEY `name` (`name`)  <<-- new key here
  KEY `display` (`display_order`) <<--new key here
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- the query
SELECT `country`.* 
FROM `country` 
WHERE `country`.`expiry_date` = 0 
ORDER BY `country`.`display_order` ASC, `country`.`name` ASC;
复合索引很棘手 MySQL不使用复合索引中ѭ3上的索引,因为ѭ3居于中间,而MySQL仅使用部分索引(如果该部分是复合索引的最左部分)。 字段显示顺序的索引也是如此。其中具有display_order的复合索引使用该字段作为其最右边的部分,因此将不进行排序。 解 为字段“ 3”创建一个单独的索引, 以及字段“ 1”的单独索引。 有时,即使索引可用,MySQL也不使用索引。发生这种情况的一种情况是,优化器估计使用索引将需要MySQL访问表中很大比例的行。 (在这种情况下,表扫描可能会更快,因为它需要更少的查找。)但是,如果这样的查询使用LIMIT只检索某些行,则MySQL仍然使用索引,因为它可以更快地找到返回结果的几行。 同样,如果很大一部分行具有相同的值(> 40%(IIRC)),则MySQL将不会使用索引。 参见:http://dev.mysql.com/doc/refman/5.1/en/mysql-indexes.html 参见:http://dev.mysql.com/doc/refman/5.1/en/index-hints.html 关于如何按照FractalizeR建议强制使用索引。 强制索引后确定选择时间 在这样一个简单的查询中,MySQL似乎不太可能出错,并且您选择的0.0013秒的时间表明表中的行很少。 当表中的行很少时,由于上面提到的百分比规则,索引无法按预期工作。 请注意,在这种情况下,强制索引将无法工作,因为您不能强制MySQL使用复合索引的最右边部分。它只是不能做到这一点。
如果您认为MySQL不明智地选择了索引,并且可以肯定,请使用
FORCE INDEX
索引提示:http://dev.mysql.com/doc/refman/5.1/en/index-hints.html
您的查询在{display_order} + {name}列上有一个ORDER BY,而 实际上,您的名为\“ display_order \”的索引是在{expiry_date} + {name} + {display_order}列上定义的。 索引中列的顺序确实很重要。如果需要对作为索引开头的列进行排序排序,则可以使索引受益。 如果您牢记索引是预排序的信息,这将变得显而易见。 如果您想受益于{display_order} + {name}上的索引,则需要以{display_order} + {name}开头的索引。例如{display_order} + {name}或{display_order} + {name} + {expiry_date}。 因此,为了优化查询,您必须更改表中的索引或查询中的SORT子句。
您可以做的最后一件事是,使用fractalizeR提到的“ FORCE INDEX”

要回复问题请先登录注册