我试图针对当前非常慢的查询优化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
表中添加了几个索引...
......这里是file_storage
表的索引......
......但它仍然很慢!比如跑20秒钟。
EXPLAIN
告诉我正在使用filesort
:
我以为我可以通过为filesort
和WHERE
子句中提到的所有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;
答案 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
同时尽量不要选择*
,只选择必要的列。