如何使用多个JOINS改进MYSQL查询

时间:2015-08-26 23:15:30

标签: mysql performance join

我有2个搜索页面,在获取结果时速度非常慢。

我没有写查询,但我知道它们不是以有效的方式编写的;我在MYSQL中没有足够的练习来弄清楚如何提高它们的效率。

如何改进以下查询?

SELECT DISTINCT m.id AS memberID , m.login , m.age , p.gender
 , p.name AS header , p.id AS profileID , p.city , p.state , p.lastlogin
 , o.login AS online , c.name AS country , ph.filename_1 AS pic 
FROM dt_members AS m 
INNER JOIN dt_profile_approved AS p ON m.id=p.member_id 
LEFT JOIN dt_privacy AS pv ON m.id=pv.member_id 
INNER JOIN dt_countries AS c ON c.id=p.country 
LEFT JOIN dt_photos AS ph ON m.id=ph.member_id 
LEFT JOIN dt_usersonline AS o ON m.login=o.login 
WHERE p.status=1 AND (pv.unsearchable IS NULL OR pv.unsearchable='') 
AND p.gender='Female' AND m.age BETWEEN 25 AND 40 
ORDER BY p.lastlogin DESC 
LIMIT 0, 21;   

非常慢,经常出现500错误。

解释输出:

EXPLAIN RESULTS

显示创建表:

CREATE TABLE `dt_members` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `login` varchar(25) DEFAULT NULL,
 `pswd` varchar(20) DEFAULT NULL,
 `email` varchar(255) DEFAULT NULL,
 `name` varchar(40) DEFAULT NULL,
 `gender` varchar(10) DEFAULT NULL,
 `age` int(11) DEFAULT NULL,
 `country` varchar(255) DEFAULT NULL,
 `looking_for` varchar(255) DEFAULT NULL,
 `ip_addr` varchar(15) DEFAULT NULL,
 `reg_date` int(11) DEFAULT NULL,
 `status` int(11) DEFAULT NULL,
 `system_status` int(11) DEFAULT '0',
 `system_status_end` int(11) DEFAULT NULL,
 `unlimited` int(11) DEFAULT '0',
 `unlimited_end` int(11) DEFAULT NULL,
 `matchfinder` int(1) DEFAULT '0',
 PRIMARY KEY (`id`),
 KEY `login` (`login`),
 KEY `pswd` (`pswd`),
 KEY `email` (`email`),
 KEY `name` (`name`),
 KEY `gender` (`gender`),
 KEY `age` (`age`),
 KEY `country` (`country`),
 KEY `looking_for` (`looking_for`),
 KEY `ip_addr` (`ip_addr`),
 KEY `reg_date` (`reg_date`),
 KEY `status` (`status`),
 KEY `system_status` (`system_status`),
 KEY `system_status_end` (`system_status_end`),
 KEY `unlimited` (`unlimited`),
 KEY `unlimited_end` (`unlimited_end`),
 KEY `matchfinder` (`matchfinder`)
) ENGINE=MyISAM AUTO_INCREMENT=29150 DEFAULT CHARSET=latin1

 CREATE TABLE `dt_profile` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `member_id` int(11) DEFAULT NULL,
 `country` int(11) DEFAULT NULL,
 `state` varchar(255) DEFAULT NULL,
 `city` varchar(255) DEFAULT NULL,
 `email` varchar(255) DEFAULT NULL,
 `name` varchar(255) DEFAULT NULL,
 `gender` varchar(20) DEFAULT NULL,
 `birth_day` int(11) DEFAULT NULL,
 `birth_month` varchar(6) DEFAULT NULL,
 `birth_year` int(11) DEFAULT NULL,
 `marital_status` int(11) DEFAULT NULL,
 `children` int(11) DEFAULT NULL,
 `drinking` int(11) DEFAULT NULL,
 `smoking` int(11) DEFAULT NULL,
 `food` int(11) DEFAULT NULL,
 `eye_color` int(11) DEFAULT NULL,
 `hair_color` int(11) DEFAULT NULL,
 `height` int(11) DEFAULT NULL,
 `body_type` int(11) DEFAULT NULL,
 `race` int(11) DEFAULT NULL,
 `religion` int(11) DEFAULT NULL,
 `occupation` int(11) DEFAULT NULL,
 `education` int(11) DEFAULT NULL,
 `lang_1` int(11) DEFAULT NULL,
 `lang_1_rate` int(11) DEFAULT NULL,
 `lang_2` int(11) DEFAULT NULL,
 `lang_2_rate` int(11) DEFAULT NULL,
 `lang_3` int(11) DEFAULT NULL,
 `lang_3_rate` int(11) DEFAULT NULL,
 `lang_4` int(11) DEFAULT NULL,
 `lang_4_rate` int(11) DEFAULT NULL,
 `looking_for` varchar(10) DEFAULT NULL,
 `age_from` int(11) DEFAULT NULL,
 `age_to` int(11) DEFAULT NULL,
 `general_info` text,
 `appearance_info` text,
 `looking_for_info` text,
 `status` int(11) DEFAULT NULL,
 `finish_status` int(11) DEFAULT NULL,
 `not_newbie` int(11) DEFAULT NULL,
 `lastlogin` int(10) NOT NULL DEFAULT '0',
 `zipcode` varchar(5) NOT NULL DEFAULT '',
 `longitude` double DEFAULT NULL,
 `latitude` double DEFAULT NULL,
 `photo_pass` varchar(25) NOT NULL DEFAULT '',
 `view_count` int(11) DEFAULT '0',
 `wants_kids` int(11) DEFAULT NULL,
 `kids_okay` int(11) DEFAULT NULL,
 `relocate_domestic` int(11) DEFAULT NULL,
 `relocate_international` int(11) DEFAULT NULL,
 `pioneer` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `member_id` (`member_id`),
 KEY `country` (`country`),
 KEY `state` (`state`),
 KEY `city` (`city`),
 KEY `email` (`email`),
 KEY `name` (`name`),
 KEY `gender` (`gender`),
 KEY `birth_day` (`birth_day`),
 KEY `birth_month` (`birth_month`),
 KEY `birth_year` (`birth_year`),
 KEY `marital_status` (`marital_status`),
 KEY `children` (`children`),
 KEY `drinking` (`drinking`),
 KEY `smoking` (`smoking`),
 KEY `food` (`food`),
 KEY `eye_color` (`eye_color`),
 KEY `hair_color` (`hair_color`),
 KEY `height` (`height`),
 KEY `body_type` (`body_type`),
 KEY `race` (`race`),
 KEY `religion` (`religion`),
 KEY `occupation` (`occupation`),
 KEY `education` (`education`),
 KEY `lang_1` (`lang_1`),
 KEY `lang_1_rate` (`lang_1_rate`),
 KEY `lang_2` (`lang_2`),
 KEY `lang_2_rate` (`lang_2_rate`),
 KEY `lang_3` (`lang_3`),
 KEY `lang_3_rate` (`lang_3_rate`),
 KEY `lang_4` (`lang_4`),
 KEY `lang_4_rate` (`lang_4_rate`),
 KEY `looking_for` (`looking_for`),
 KEY `age_from` (`age_from`),
 KEY `age_to` (`age_to`),
 KEY `status` (`status`),
 KEY `finish_status` (`finish_status`),
 KEY `not_newbie` (`not_newbie`),
 KEY `lastlogin` (`lastlogin`),
 KEY `zipcode` (`zipcode`),
 KEY `longitude` (`longitude`),
 KEY `latitude` (`latitude`),
 KEY `photo_pass` (`photo_pass`),
 KEY `view_count` (`view_count`),
 KEY `wants_kids` (`wants_kids`),
 KEY `kids_okay` (`kids_okay`),
 KEY `relocate_domestic` (`relocate_domestic`),
 KEY `relocate_international` (`relocate_international`),
 KEY `pioneer` (`pioneer`)
) ENGINE=MyISAM AUTO_INCREMENT=18389 DEFAULT CHARSET=latin1

CREATE TABLE `dt_privacy` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `member_id` int(11) DEFAULT NULL,
 `online_yn` char(1) DEFAULT NULL,
 `vkiss_yn` char(1) DEFAULT NULL,
 `profiles_yn` char(1) DEFAULT NULL,
 `IM_yn` char(1) DEFAULT NULL,
 `featured_yn` char(1) DEFAULT NULL,
 `HL_messaged_yn` char(1) DEFAULT NULL,
 `HL_im_yn` char(1) DEFAULT NULL,
 `HL_viewed_yn` char(1) DEFAULT NULL,
 `HL_kissed_yn` char(1) DEFAULT NULL,
 `HL_favorite_yn` char(1) DEFAULT NULL,
 `unsearchable` char(1) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `member_id` (`member_id`),
 KEY `online_yn` (`online_yn`),
 KEY `vkiss_yn` (`vkiss_yn`),
 KEY `profiles_yn` (`profiles_yn`),
 KEY `IM_yn` (`IM_yn`),
 KEY `featured_yn` (`featured_yn`),
 KEY `HL_messaged_yn` (`HL_messaged_yn`),
 KEY `HL_im_yn` (`HL_im_yn`),
 KEY `HL_viewed_yn` (`HL_viewed_yn`),
 KEY `HL_kissed_yn` (`HL_kissed_yn`),
 KEY `HL_favorite_yn` (`HL_favorite_yn`),
 KEY `unsearchable` (`unsearchable`)
) ENGINE=MyISAM AUTO_INCREMENT=26305 DEFAULT CHARSET=latin1

CREATE TABLE `dt_countries` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(100) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `name` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=226 DEFAULT CHARSET=latin1

CREATE TABLE `dt_photos` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `member_id` varchar(255) DEFAULT NULL,
 `filename_1` varchar(255) DEFAULT NULL,
 `filename_2` varchar(255) DEFAULT NULL,
 `filename_3` varchar(255) NOT NULL DEFAULT '',
 `filename_4` varchar(255) NOT NULL DEFAULT '',
 `filename_5` varchar(255) NOT NULL DEFAULT '',
 `filename_6` varchar(255) NOT NULL DEFAULT '',
 `filename_7` varchar(255) NOT NULL DEFAULT '',
 `filename_8` varchar(255) NOT NULL DEFAULT '',
 `filename_9` varchar(255) NOT NULL DEFAULT '',
 `filename_10` varchar(255) NOT NULL DEFAULT '',
 `filename_11` varchar(255) NOT NULL DEFAULT '',
 `filename_12` varchar(255) NOT NULL DEFAULT '',
 `filename_13` varchar(255) NOT NULL DEFAULT '',
 `filename_14` varchar(255) NOT NULL DEFAULT '',
 `filename_15` varchar(255) NOT NULL DEFAULT '',
 `filename_16` varchar(255) NOT NULL DEFAULT '',
 `filename_17` varchar(255) NOT NULL DEFAULT '',
 `filename_18` varchar(255) NOT NULL DEFAULT '',
 `filename_19` varchar(255) NOT NULL DEFAULT '',
 `filename_20` varchar(255) NOT NULL DEFAULT '',
 `private_1` tinyint(1) NOT NULL DEFAULT '0',
 `private_2` tinyint(1) NOT NULL DEFAULT '0',
 `private_3` tinyint(1) NOT NULL DEFAULT '0',
 `private_4` tinyint(1) NOT NULL DEFAULT '0',
 `private_5` tinyint(1) NOT NULL DEFAULT '0',
 `private_6` tinyint(1) NOT NULL DEFAULT '0',
 `private_7` tinyint(1) NOT NULL DEFAULT '0',
 `private_8` tinyint(1) NOT NULL DEFAULT '0',
 `private_9` tinyint(1) NOT NULL DEFAULT '0',
 `private_10` tinyint(1) NOT NULL DEFAULT '0',
 `private_11` tinyint(1) NOT NULL DEFAULT '0',
 `private_12` tinyint(1) NOT NULL DEFAULT '0',
 `private_13` tinyint(1) NOT NULL DEFAULT '0',
 `private_14` tinyint(1) NOT NULL DEFAULT '0',
 `private_15` tinyint(1) NOT NULL DEFAULT '0',
 `private_16` tinyint(1) NOT NULL DEFAULT '0',
 `private_17` tinyint(1) NOT NULL DEFAULT '0',
 `private_18` tinyint(1) NOT NULL DEFAULT '0',
 `private_19` tinyint(1) NOT NULL DEFAULT '0',
 `private_20` tinyint(1) NOT NULL DEFAULT '0',
 `password` varchar(255) NOT NULL DEFAULT '',
 `description_1` varchar(255) DEFAULT NULL,
 `description_2` varchar(255) DEFAULT NULL,
 `description_3` varchar(255) NOT NULL DEFAULT '',
 `description_4` varchar(255) NOT NULL DEFAULT '',
 `description_5` varchar(255) NOT NULL DEFAULT '',
 `description_6` varchar(255) NOT NULL DEFAULT '',
 `description_7` varchar(255) NOT NULL DEFAULT '',
 `description_8` varchar(255) NOT NULL DEFAULT '',
 `description_9` varchar(255) NOT NULL DEFAULT '',
 `description_10` varchar(255) NOT NULL DEFAULT '',
 `description_11` varchar(255) NOT NULL DEFAULT '',
 `description_12` varchar(255) NOT NULL DEFAULT '',
 `description_13` varchar(255) NOT NULL DEFAULT '',
 `description_14` varchar(255) NOT NULL DEFAULT '',
 `description_15` varchar(255) NOT NULL DEFAULT '',
 `description_16` varchar(255) NOT NULL DEFAULT '',
 `description_17` varchar(255) NOT NULL DEFAULT '',
 `description_18` varchar(255) NOT NULL DEFAULT '',
 `description_19` varchar(255) NOT NULL DEFAULT '',
 `description_20` varchar(255) NOT NULL DEFAULT '',
 PRIMARY KEY (`id`),
 KEY `filename_12` (`filename_12`),
 KEY `filename_13` (`filename_13`),
 KEY `filename_14` (`filename_14`),
 KEY `filename_15` (`filename_15`),
 KEY `filename_16` (`filename_16`),
 KEY `filename_17` (`filename_17`),
 KEY `filename_18` (`filename_18`),
 KEY `filename_19` (`filename_19`),
 KEY `filename_20` (`filename_20`),
 KEY `member_id` (`member_id`),
 KEY `filename_1` (`filename_1`),
 KEY `filename_2` (`filename_2`),
 KEY `filename_3` (`filename_3`),
 KEY `filename_4` (`filename_4`),
 KEY `filename_5` (`filename_5`),
 KEY `filename_6` (`filename_6`),
 KEY `filename_7` (`filename_7`),
 KEY `filename_8` (`filename_8`),
 KEY `filename_9` (`filename_9`),
 KEY `filename_10` (`filename_10`),
 KEY `private_1` (`private_1`),
 KEY `private_2` (`private_2`),
 KEY `private_3` (`private_3`),
 KEY `private_4` (`private_4`),
 KEY `private_5` (`private_5`),
 KEY `private_6` (`private_6`),
 KEY `private_7` (`private_7`),
 KEY `private_8` (`private_8`),
 KEY `private_9` (`private_9`),
 KEY `private_10` (`private_10`),
 KEY `private_11` (`private_11`),
 KEY `private_12` (`private_12`),
 KEY `private_13` (`private_13`),
 KEY `private_14` (`private_14`),
 KEY `private_15` (`private_15`),
 KEY `private_16` (`private_16`),
 KEY `private_17` (`private_17`),
 KEY `private_18` (`private_18`),
 KEY `private_19` (`private_19`),
 KEY `private_20` (`private_20`),
 KEY `password` (`password`),
 KEY `description_1` (`description_1`),
 KEY `description_2` (`description_2`),
 KEY `description_3` (`description_3`),
 KEY `description_4` (`description_4`),
 KEY `description_5` (`description_5`),
 KEY `description_6` (`description_6`),
 KEY `description_7` (`description_7`),
 KEY `description_8` (`description_8`),
 KEY `description_9` (`description_9`),
 KEY `description_10` (`description_10`),
 KEY `description_11` (`description_11`),
 KEY `description_12` (`description_12`),
 KEY `description_13` (`description_13`),
 KEY `description_14` (`description_14`),
 KEY `description_15` (`description_15`),
 KEY `description_16` (`description_16`),
 KEY `description_17` (`description_17`),
 KEY `description_18` (`description_18`),
 KEY `description_19` (`description_19`),
 KEY `description_20` (`description_20`),
 KEY `filename_10_2` (`filename_10`),
 KEY `filename_10_3` (`filename_10`)
) ENGINE=MyISAM AUTO_INCREMENT=11174 DEFAULT CHARSET=latin1

 CREATE TABLE `dt_usersonline` (
 `id` int(8) NOT NULL AUTO_INCREMENT,
 `timestamp` int(15) NOT NULL DEFAULT '0',
 `ip` varchar(40) NOT NULL DEFAULT '',
 `login` varchar(25) NOT NULL DEFAULT '',
 `userid` int(10) NOT NULL DEFAULT '0',
 `session_id` varchar(255) NOT NULL DEFAULT '',
 PRIMARY KEY (`id`),
 KEY `id_2` (`id`),
 KEY `timestamp` (`timestamp`),
 KEY `ip` (`ip`),
 KEY `login` (`login`),
 KEY `userid` (`userid`),
 KEY `session_id` (`session_id`)
) ENGINE=MyISAM AUTO_INCREMENT=4424348 DEFAULT CHARSET=latin1

2 个答案:

答案 0 :(得分:2)

CREATE TABLE `dt_members` (
 `id` int(11) NOT NULL AUTO_INCREMENT,...

    CREATE TABLE `dt_photos` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `member_id` varchar(255) DEFAULT NULL,..

您正在加入您的查询:

LEFT JOIN dt_photos AS ph ON m.id=ph.member_id

请注意,您在member_idm.id的所有其他时间加入该列的方式如何member_id int(11) DEFAULT NULL。您的连接条件应该是相同的数据类型,否则它看起来像是在进行全表扫描。它没有使用密钥,因为它认为它必须扫描varchar字段而不是使用on子句的索引。

member_id

尝试Alteringm.iddt_members

值得注意的是,如果你真的试图创建一个外键约束,那么由于数据类型不匹配,它不会允许你...

警告:MYISAM表将在后续表进程的持续时间内被锁定。

答案 1 :(得分:0)

尝试将条件移动到相应的连接条件中:

private void Dispose(bool)

在所有连接之后的条件的情况下,在连接期间会评估连接条件,因此可以提前避免大量不必要的连接。

虽然理论上查询优化器应该为你做这个,但我发现mysql在这方面可能特别密集。​​