MySQL:如何防止带有ORDER BY中使用的列的索引的文件排序

时间:2015-04-03 13:27:21

标签: php mysql sql join query-optimization

我试图针对当前非常慢的查询优化MySQL数据库:

SELECT  Listing.*,  PrimaryPhoto.* 
 FROM listings AS Listing  
 LEFT JOIN file_storage AS PrimaryPhoto  
 ON (PrimaryPhoto.foreign_key  =  Listing.ID  
 AND  PrimaryPhoto.model  = 'PrimaryListingPhoto') 
 WHERE  Listing.rent  >= 0 
 AND  Listing.rent  <= 5000 
 AND  Listing.beds  >= 1 
 AND  Listing.is_active  = '1' 
 ORDER BY Listing.modified  DESC

我已在listings表中添加了几个索引... enter image description here ......这里是file_storage表的索引...... enter image description here ......但它仍然很慢!比如跑20秒钟。

EXPLAIN告诉我正在使用filesortenter image description here

我以为我可以通过为filesortWHERE子句中提到的所有4列添加索引来阻止ORDER BY。但它还没有奏效。

我做错了什么吗?或者我可能正在寻找错误的地方来加快这个问题。

更新 以下是两个表的架构:

CREATE TABLE IF NOT EXISTS `listings` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT 'ID of user who owns this listing', `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `address` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT 'Street address (w/o postal code)', `lat` decimal(10,8) DEFAULT NULL, `lng` decimal(11,8) DEFAULT NULL, `postal_code` varchar(20) COLLATE utf8_unicode_ci NOT NULL, `description` text COLLATE utf8_unicode_ci NOT NULL, `rent` int(11) NOT NULL COMMENT 'Monthly rental price in CAD', `lease_length` int(11) DEFAULT NULL COMMENT '# of months of lease', `date_available` date DEFAULT NULL COMMENT 'Day the listing is available', `neighborhood_id` int(11) NOT NULL, `beds` int(11) NOT NULL COMMENT '# of bedrooms', `baths` int(11) NOT NULL COMMENT '# of bathrooms', `sq_ft` int(11) DEFAULT NULL COMMENT '# of square footage', `fridge` tinyint(1) NOT NULL, `stove` tinyint(1) NOT NULL, `dishwasher` tinyint(1) NOT NULL, `ac` tinyint(1) NOT NULL, `furnished` tinyint(1) NOT NULL, `laundry` tinyint(1) NOT NULL, `balcony` tinyint(1) NOT NULL, `patio` tinyint(1) NOT NULL, `yard` tinyint(1) NOT NULL, `pool` tinyint(1) NOT NULL, `doorman` tinyint(1) NOT NULL, `security` tinyint(1) NOT NULL, `gym` tinyint(1) NOT NULL, `parking` tinyint(1) NOT NULL, `wheelchair` tinyint(1) NOT NULL, `inc_heat` tinyint(1) NOT NULL COMMENT 'does the rent include heat?', `inc_water` tinyint(1) NOT NULL COMMENT 'doest the rent include water?', `inc_internet` tinyint(1) NOT NULL COMMENT 'does the rent include internet?', `inc_cable` tinyint(1) NOT NULL COMMENT 'does the rent include cable?', `cats` tinyint(1) NOT NULL COMMENT 'are cats allowed?', `small_dogs` tinyint(1) NOT NULL COMMENT 'are small dogs allowed?', `big_dogs` tinyint(1) NOT NULL COMMENT 'are big dogs allowed?', `is_active` tinyint(1) NOT NULL COMMENT 'is the listing active?', `is_hot` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'hot list', `source_url` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `source_email` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, PRIMARY KEY (`ID`), KEY `user_id` (`user_id`), KEY `is_active` (`is_active`), KEY `rent` (`rent`), KEY `rent_beds_is_active` (`rent`,`beds`,`is_active`), KEY `modified` (`modified`), KEY `rent_beds_active_modified` (`rent`,`beds`,`is_active`,`modified`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3012 ;

CREATE TABLE IF NOT EXISTS `file_storage` ( `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, `user_id` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, `foreign_key` varchar(36) COLLATE utf8_unicode_ci DEFAULT NULL, `model` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `filename` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `filesize` int(16) DEFAULT NULL, `mime_type` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL, `extension` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL, `hash` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `path` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `adapter` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Gaufrette Storage Adapter Class', `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `foreign_key` (`foreign_key`), KEY `model_foreign_key` (`model`,`foreign_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

2 个答案:

答案 0 :(得分:1)

这是您的查询:

SELECT  Listing.*,  PrimaryPhoto.* 
FROM listings AS Listing LEFT JOIN
     file_storage AS PrimaryPhoto  
     ON PrimaryPhoto.foreign_key  =  Listing.ID  AND 
        PrimaryPhoto.model  = 'PrimaryListingPhoto'
WHERE Listing.rent >= 0 AND  Listing.rent  <= 5000 AND
      Listing.beds  >= 1 AND
      Listing.is_active  = '1' 
ORDER BY Listing.modified  DESC

尝试此复合索引(键的顺序很重要):Listing(beds, is_active, modified, rent)where上的完整索引(即beds, is_active, rent)order by没有帮助。这个可能。此外,您需要file_storage(foreign_key, model)上的索引。

答案 1 :(得分:0)

删除PrimaryPhoto.model上的索引并删除连接,将其添加到where子句。您的查询应如下所示:

SELECT  Listing.*,  PrimaryPhoto.* 
 FROM listings AS Listing  
 LEFT JOIN file_storage AS PrimaryPhoto  
 ON PrimaryPhoto.foreign_key  =  Listing.ID
 WHERE  Listing.rent  >= 0 
 AND  Listing.rent  <= 5000 
 AND  Listing.beds  >= 1 
 AND  Listing.is_active  = '1' 
 AND  PrimaryPhoto.model  = 'PrimaryListingPhoto'
 ORDER BY Listing.modified  DESC

同时尽量不要选择*,只选择必要的列。