使用慢MYSQL文件排序性能(MYSQL performance slow using fileso

2019-06-27 10:37发布

我有一个简单的MySQL查询,但是当我有很多的记录(目前103,0000),性能实在是太慢了,它说,它是使用文件排序,林不知道这是为什么它是缓慢的。 有没有人有任何建议,以加快步伐? 或使用文件排序停止吗?

MySQL查询:

SELECT adverts .*    
FROM adverts
WHERE (
price >='0'
)
AND (
adverts.status = 1
)
AND (
adverts.approved = 1
)
ORDER BY date_updated DESC 
LIMIT 19990 , 10

该解释的结果:

id   select_type   table   type    possible_keys    key    key_len    ref    rows   Extra 
1    SIMPLE        adverts range   price            price  4          NULL   103854 Using where; Using filesort

下面是广告表和索引:

CREATE TABLE `adverts` (
  `advert_id` int(10) NOT NULL AUTO_INCREMENT,
  `user_id` int(10) NOT NULL,
  `type_id` tinyint(1) NOT NULL,
  `breed_id` int(10) NOT NULL,
  `advert_type` tinyint(1) NOT NULL,
  `headline` varchar(50) NOT NULL,
  `description` text NOT NULL,
  `price` int(4) NOT NULL,
  `postcode` varchar(7) NOT NULL,
  `town` varchar(60) NOT NULL,
  `county` varchar(60) NOT NULL,
  `latitude` float NOT NULL,
  `longitude` float NOT NULL,
  `telephone1` varchar(15) NOT NULL,
  `telephone2` varchar(15) NOT NULL,
  `email` varchar(80) NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '0',
  `approved` tinyint(1) NOT NULL DEFAULT '0',
  `date_created` datetime NOT NULL,
  `date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `expiry_date` datetime NOT NULL,
  PRIMARY KEY (`advert_id`),
  KEY `price` (`price`),
  KEY `user` (`user_id`),
  KEY `type_breed` (`type_id`,`breed_id`),
  KEY `headline_keywords` (`headline`),
  KEY `date_updated` (`date_updated`),
  KEY `type_status_approved` (`advert_type`,`status`,`approved`)
) ENGINE=MyISAM AUTO_INCREMENT=103878 DEFAULT CHARSET=utf8

Answer 1:

问题是,MySQL的执行查询时只使用一个索引。 如果您添加使用3个字段中输入您在新的索引WHERE子句,它会更快找到行。

ALTER TABLE `adverts` ADD INDEX price_status_approved(`price`, `status`, `approved`);

据MySQL文档ORDER BY优化 :

在某些情况下,MySQL不能使用索引来解决ORDER BY,尽管它仍然使用索引来找到匹配WHERE子句的行。 这些情况包括以下内容:
用于获取行的关键是不一样的,在ORDER BY中使用的一个。

这是你的情况下会发生什么。 由于输出EXPLAIN告诉我们,优化器使用的关键price ,找到行。 然而, ORDER BY在场上date_updated不属于关键price

要查找行更快,行排序更快,你需要添加包含在使用的所有字段的索引WHERE ,并在ORDER BY子句:

ALTER TABLE `adverts` ADD INDEX status_approved_date_updated(`status`, `approved`, `date_updated`);

用于排序字段必须在索引中的最后一个位置。 这是没用的,包括price的指数,因为在查询中使用的条件将返回值的范围。

如果EXPLAIN仍显示它正在使用文件排序,您可以尝试强制MySQL使用你选择的指标:

SELECT adverts.*
FROM adverts
FORCE INDEX(status_approved_date_updated)
WHERE price >= 0
AND adverts.status = 1
AND adverts.approved = 1
ORDER BY date_updated DESC 
LIMIT 19990, 10

它通常是没有必要强制指标,因为MySQL优化最常做了正确的选择。 但有时它使一个不错的选择,或者不是最好的选择。 您将需要运行一些测试,看看它是否可以提高性能或没有。



Answer 2:

删除周围的蜱'0' -目前它可以防止使用索引,但我不知道。 尽管如此,它是更好的风格,因为价格是int类型,而不是一个字符列。

SELECT adverts .*    
FROM adverts
WHERE (
price >= 0
)
AND (
adverts.status = 1
)
AND (
adverts.approved = 1
)
ORDER BY date_updated DESC 
LIMIT 19990 , 10


Answer 3:

我有两个建议。 首先,删除围绕零报价的where子句。 该行应该是:

price >= 0

二,创建这个索引:

CREATE INDEX `helper` ON `adverts`(`status`,`approved`,`price`,`date_created`);

这应该允许MySQL的仅使用索引来查找你的LIMIT子句指定的10行。 文件排序本身并不是一件坏事......这需要处理的行数。



Answer 4:

你的WHERE条件使用pricestatusapproved选择,然后date_updated来排序。

所以,你需要这些领域的单一指数; 我建议在索引approvedstatuspricedate_updated ,在这个秩序。

一般的规则是将WHERE第一等式,则范围(大于,小于或等于,之间,等等),和排序字段最后。 (请注意,留下一个领域出可能赚了指数少使用,甚至无法使用,为了这个目的)。

CREATE INDEX advert_ndx ON adverts (approved, status, price, date_updated);

这样一来,对表的访问数据后,才需要LIMIT已经发挥了奇效,你将放缓,仅检索少量的记录。

我还删除任何不必要的索引,这将加快INSERT S和UPDATE秒。



Answer 5:

MySQL不使用的关键date_updated的排序,但只使用了price的关键,因为它是在使用中的WHERE子句中。 您可以尝试使用索引提示:

http://dev.mysql.com/doc/refman/5.1/en/index-hints.html

添加类似

USE KEY FOR ORDER BY  (date_updated)


文章来源: MYSQL performance slow using filesort