MySQL左连接对于大量数据需要太长时间

时间:2015-10-15 08:30:35

标签: mysql sql

我有两个表.Property表和它相关的photo.One属性可能有很多照片,但我只想要一个相关的照片,当我使用左连接MySQL查询它变得太慢。

这是我的查询

SELECT `sp_property`.`id` as propertyid, `sp_property`.`property_name`, `sp_property`.`property_price`, `sp_property`.`adv_type`, `sp_property`.`usd`, `images`.`filepath_name` 
FROM (`sp_property`) 
LEFT JOIN  (select id, Max(property_id) as pid,filepath_name 
            from sp_property_images
            group by property_id) `images`
ON `images`.`pid` = `sp_property`.`id` 
WHERE `sp_property`.`published` = 'yes' 
GROUP BY `propertyid` 
ORDER BY `sp_property`.`feature_listing` desc, `submit_date` desc
LIMIT 1,20



CREATE TABLE IF NOT EXISTS `sp_property_images` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` varchar(100) NOT NULL,
  `filepath_name` text,
  `label_name` varchar(45) DEFAULT NULL,
  `primary` char(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `property_id` (`property_id`),
  KEY `id` (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=12941 ;

CREATE TABLE IF NOT EXISTS `sp_property` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `propertytype` varchar(50) NOT NULL,
  `adv_type` varchar(45) NOT NULL,
  `property_name` text,
  `division` varchar(45) NOT NULL,
  `township` varchar(45) NOT NULL,
  `property_price` decimal(20,2) unsigned DEFAULT NULL,
  `price_type` varchar(45) NOT NULL,
  `availability` varchar(100) DEFAULT NULL,
  `property_address` text,
  `p_dimension_length` varchar(45) NOT NULL,
  `p_dimension_width` varchar(45) NOT NULL,
  `p_dimension_sqft` varchar(45) NOT NULL,
  `p_dimension_acre` varchar(45) NOT NULL,
  `floor` varchar(45) NOT NULL,
  `phone` varchar(100) DEFAULT NULL,
  `aircorn` varchar(45) NOT NULL,
  `ownership` varchar(45) NOT NULL,
  `bedroom` varchar(45) NOT NULL,
  `bathroom` varchar(45) NOT NULL,
  `special_feature` text,
  `amentites` text,
  `property_detail` text,
  `submit_date` datetime DEFAULT NULL,
  `published` varchar(45) NOT NULL,
  `published_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `agent_id` varchar(45) NOT NULL,
  `source` varchar(45) NOT NULL,
  `contact_name` varchar(100) NOT NULL,
  `contact_no` varchar(100) NOT NULL,
  `contact_address` text NOT NULL,
  `contact_email` varchar(100) NOT NULL,
  `unit_type` varchar(100) DEFAULT NULL,
  `map_lat` varchar(100) DEFAULT NULL,
  `map_long` varchar(100) DEFAULT NULL,
  `show_map` varchar(3) DEFAULT 'no',
  `total_view` bigint(20) NOT NULL DEFAULT '0',
  `feature_listing` varchar(10) NOT NULL DEFAULT 'no',
  `new_homes_id` int(11) NOT NULL,
  `publish_price` int(1) NOT NULL DEFAULT '0',
  `usd` decimal(20,2) NOT NULL,
  `tag_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18524 ;

2 个答案:

答案 0 :(得分:0)

您是否在表上添加了索引?您需要在以下列中使用三个索引:

  • article_photo.a_id用于分组和加入
  • article_photo.p_id进行排序
  • article.a_id加入(虽然希望已经是你桌子的PK)

连接的结果不保证按任何顺序排序,因此您可能希望将子ORDER BY子句从子查询移动到外部查询:

 SELECT * from `article` 
 LEFT JOIN (
 SELECT * from `article_photo`  
 GROUP BY `a_id`) as images 
 ON article.a_id = images.a_id
 ORDER BY images.p_id DESC

此外,您无法保证您将获得article_photo,因为选择没有聚合功能的数据(只有MySQL才允许您这样做)。

既然这个问题包含真实的表格以及回答所必需的所有信息,这里是我的第一步,这是你的问题:

SELECT `sp_property`.`id` as propertyid, `sp_property`.`property_name`, `sp_property`.`property_price`, `sp_property`.`adv_type`, `sp_property`.`usd`, `images`.`filepath_name` 
FROM (`sp_property`) 
LEFT JOIN  (select id, Max(property_id) as pid,filepath_name 
            from sp_property_images
            group by property_id) `images`
ON `images`.`pid` = `sp_property`.`id` 
WHERE `sp_property`.`published` = 'yes' 
GROUP BY `propertyid` 
ORDER BY `sp_property`.`feature_listing` desc, `submit_date` desc
LIMIT 1,20

我们来看看。您正在sp_property_images.property_id加入sp_property.id。这些列具有不同的类型(intvarchar),我认为这会导致严重的性能损失(因为必须将值转换为相同的类型)。

然后,您按sp_property.published进行过滤,因此我建议您在此列上添加索引。另外,检查是否确实需要将此列作为varchar。 bool / bit标志也可能就足够了(如果没有,枚举可能仍然是更好的选择)。

也可以从索引中获得好处。添加一个跨两个sp_property.feature_listingsp_property.submit_date的索引。

如果上述所有操作仍无效,则可能必须删除子选择。它可能会阻止mysql引擎识别(并使用!)您在sp_property_images.property_id列上定义的索引。

答案 1 :(得分:0)

这个简单的查询将为您提供所要求的内容,所有文章及其照片

SELECT ar.a_id, ar.a_title, ap.p_id, ap.photo_name 
FROM article ar
JOIN article_photo ap on ar.a_id = ap.a_id

没有理由在那里留下加入和分组,或者你想按照文章对照片进行总结?