【发布时间】:2015-06-08 14:22:00
【问题描述】:
我正在尝试针对当前非常慢的查询优化 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 正在被使用:
我认为我可以通过为 WHERE 和 ORDER BY 子句中提到的所有 4 列添加索引来防止 filesort。但它没有奏效。
我做错了吗?或者,也许我正在寻找错误的地方来加速这个查询。
更新 这是两个表的架构:
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;
【问题讨论】:
-
这个查询产生多少结果?
-
@eggyal 在生产中,目前将返回 975 个结果
-
我看到在你的
file_storage表中你有一个复合索引(模型,foreign_key)。尝试仅在model上添加索引。 -
@Daan 我只为
model添加了一个索引,但它似乎没有多大作用。基数是 20。 -
两个表有多少列和记录?你能张贴表格吗?
标签: php mysql sql join query-optimization