MySQL GROUP BY函数需要很长时间

时间:2017-11-04 19:12:30

标签: mysql performance optimization group-by

我一直在使用以下查询来搜索某些数据。如果有任何设计错误,我是一个新的。请原谅。

SELECT
    j.applicant_uid,
    j.job_id,u.id,
    MAX(u.name),
    ui.phone,
    ui.fullname,
    ui.img,
    ui.address,
    u.r_date,
    r.sex,
    r.present_salary,
    w.working,
    w.description,
    e.institute_name,
    e.exam_name,
    ROUND(DATEDIFF(w.time_start, w.time_end) / 365.25) AS experience,
    ROUND(DATEDIFF(CURDATE(),r.dob) / 365.25) AS age,
    r. preferred_district,
    e.major_group ,
    w.compnay_name,
    w.designation,
    j.ukey
FROM job_apply as j               
INNER JOIN users u            ON j.applicant_uid = u.id
INNER JOIN resume r           ON j.applicant_uid = r.uid
INNER JOIN work_history w     ON j.applicant_uid = w.uid 
INNER JOIN education e        ON j.applicant_uid = e.uid
INNER JOIN user_other_info ui ON j.applicant_uid = ui.uid
WHERE `j.job_id`='131'
  AND `r.sex`                 LIKE '%1%'
  AND  `r.preferred_district` LIKE '%14%'
  AND `w.description`         LIKE '%brac%'
   OR `e.exam_name`           LIKE '%brac%'
   OR `w.compnay_name`        LIKE '%brac%'
   OR `w.designation`         LIKE '%brac%'
   OR `e.institute_name`      LIKE '%brac%'
GROUP BY `u.id`
HAVING `experience` >= '1'
  AND `r.present_salary` BETWEEN '15000' AND '20000'

但它需要大约30.017秒。如何减少查询时间?可能是什么原因?我已经添加了别名。

    CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(500) NOT NULL,
    `role_type` int(11) NOT NULL,
    `user_type` int(3) NOT NULL,
    `umail` varchar(100) NOT NULL,
    `user_pass` varchar(100) NOT NULL,
    `block` int(2) NOT NULL DEFAULT '0',
    `r_date` date NOT NULL,
    `u_date` date NOT NULL,
     PRIMARY KEY (`id`)
     ) ENGINE=InnoDB AUTO_INCREMENT=4560 DEFAULT CHARSET=latin1

这是简历表:

    CREATE TABLE `resume` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `uid` int(11) NOT NULL,
 `career_objective` varchar(5000) CHARACTER SET utf8 NOT NULL,
 `father` varchar(100) CHARACTER SET utf8 NOT NULL,
 `mother` varchar(100) CHARACTER SET utf8 NOT NULL,
 `dob` date NOT NULL DEFAULT '0000-00-00',
 `birth_place` varchar(100) CHARACTER SET utf8 NOT NULL,
 `nationality` varchar(100) CHARACTER SET utf8 NOT NULL,
 `sex` varchar(50) CHARACTER SET utf8 NOT NULL,
 `looking_for` int(3) NOT NULL,
 `present_salary` varchar(100) CHARACTER SET utf8 NOT NULL,
 `expected_salary` varchar(10) CHARACTER SET utf8 NOT NULL,
 `preferred_category` varchar(10) CHARACTER SET utf8 NOT NULL,
 `preferred_district` varchar(10) CHARACTER SET utf8 NOT NULL,
 `declaration` varchar(1000) CHARACTER SET utf8 NOT NULL,
 `facebook_link` varchar(1000) CHARACTER SET utf8 NOT NULL,
 `linkedin_link` varchar(1000) CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1905 DEFAULT CHARSET=latin1

以下是:

    CREATE TABLE `education` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `uid` int(11) NOT NULL,
 `institute_name` varchar(500) CHARACTER SET utf8 NOT NULL,
 `exam_name` varchar(100) CHARACTER SET utf8 NOT NULL,
 `major_group` varchar(100) CHARACTER SET utf8 NOT NULL,
 `result` varchar(100) CHARACTER SET utf8 NOT NULL,
 `passing_year` varchar(100) CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5279 DEFAULT CHARSET=latin1

这是job_apply表。请考虑db设计错误:

    CREATE TABLE `job_apply` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `job_id` int(11) NOT NULL,
 `applicant_uid` int(11) NOT NULL,
 `ukey` varchar(50) NOT NULL,
 `date` date NOT NULL,
 `is_short_list` int(2) NOT NULL DEFAULT '0',
 `is_rejected` int(2) NOT NULL DEFAULT '0',
 `note` varchar(5000) CHARACTER SET utf8 NOT NULL,
 `cv_viewed` int(11) NOT NULL DEFAULT '0',
 `ssc_certificate` varchar(500) CHARACTER SET utf8 NOT NULL,
 `ssc_marksheet` varchar(500) CHARACTER SET utf8 NOT NULL,
 `hsc_certificate` varchar(500) CHARACTER SET utf8 NOT NULL,
 `hsc_marksheet` varchar(500) CHARACTER SET utf8 NOT NULL,
 `graduation_certificate` varchar(500) CHARACTER SET utf8 NOT NULL,
 `graduation_marksheet` varchar(500) CHARACTER SET utf8 NOT NULL,
 `experience_certificate` varchar(500) CHARACTER SET utf8 NOT NULL,
 `recommendation_letter` varchar(500) CHARACTER SET utf8 NOT NULL,
 `ans` varchar(5000) CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2079 DEFAULT CHARSET=latin1

2 个答案:

答案 0 :(得分:0)

这里有几个问题,但有一个问题跳出了页面:你使用了像'%brac%'这样的通配符模式。请理解'brac%'可以利用索引,但带有百分号前导符号的通配符不能。你正在强迫桌面扫描。好几个,似乎。

你做了present_salary varchar(100),而不是数字,这似乎是一个非常糟糕的设计选择。如果你要求行BETWEEN '9000' and '11000'会导致麻烦,因为词典顺序与数字顺序不同。

请修改您的问题以包含SHOW CREATE TABLE job_apply的输出,还包括用户,简历,work_history,education和user_other_info。描述大概的表格大小,也许它们是数千行。最重要的是,确实包含EXPLAIN输出,以便我们看到后端优化器确定的计划。

你在几个地方加入了uid,但是你选择不为优化器提供任何一个索引,所以它被迫进行表扫描。您没有包含EXPLAIN输出,但是从架构中很明显您无法利用选择性,并且必须扫描所有表。

感谢您添加格式,这非常有帮助。

错字:w.compnay_name

你有一堆latin1表,这很好,但你可能更愿意选择默认的utf8表。令人不安的是你混合使用latin1和utf8 varchars。更好地解决一个,例如UTF8。您严格加入整数uid,但如果您曾在文本列上使用equijoin,则需要使用相同的排序规则和相同的字符集才能正确利用索引。

答案 1 :(得分:0)

我称之为"爆炸内爆综合症"。查询JOINs许多表,从而爆炸了正在查看的行数,然后它会使GROUP BY崩溃。

通常的治疗方法是认为这是两个步骤。首先,找到与各种u.id子句匹配的WHERE值。由于您将数据分散在各个表中,因此这仍然很昂贵。但是,你不会在其他几十个专栏中走动,只是为了以后扔掉很多信息。

第二步是JOIN(如果需要,再次,如果有必要)到各个表以获得所需的其他列。

建议您关注第1步的表现,因为第2步会很便宜(虽然详细)。

其他问题:

  • %中的前导通配符(LIKE)禁止使用索引。查看FULLTEXT以查找由文本组成的列。
  • 请勿查找LIKE的数字(例如sex LIKE '%1%')。
  • OR不利于性能,尤其是分布在多个表中时。
  • 是否有充分的理由将数据存储在多个(可能是两个)表中?查看单个表时,一些性能问题会减少。

还有其他问题,但这些提示可能会帮助您前进。