php - MySQL Left Join、Group By、Order By、Limit = 糟糕的性能

标签 php mysql database performance

我目前正在开发一个应用程序,允许用户使用各种参数搜索文档数据库并返回一组分页结果。我正在用 PHP/MySQL 构建它,这不是我常用的开发平台,但到目前为止它已经很棒了。

我遇到的问题是,为了返回完整的结果集,我必须在每个表上使用 LEFT JOIN,这完全破坏了我的性能。开发数据库的人说我正在使用的查询将返回正确的结果,所以这就是我必须使用的。查询在下面,我绝不是 SQL 专家,需要一些帮助。

我一直在想,将查询拆分成子查询可能会更好?以下是我当前的查询:

    SELECT d.title, d.deposition_id, d.folio_start, d.folio_end, pl.place_id, p.surname, p.forename, p.person_type_id, pt.person_type_desc, p.age, d.manuscript_number, dt.day, dt.month, dt.year, plc.county_id, c.county_desc
 FROM deposition d 
 LEFT JOIN person AS p ON p.deposition_id = d.deposition_id 
 LEFT JOIN person_type AS pt ON p.person_type_id = pt.person_type_id 
 LEFT JOIN place_link AS pl ON pl.deposition_id = d.deposition_id 
 LEFT JOIN date AS dt ON dt.deposition_id = d.deposition_id 
 LEFT JOIN place AS plc ON pl.place_id = plc.place_id 
 LEFT JOIN county AS c ON plc.county_id = c.county_id
 WHERE 1 AND d.manuscript_number = '840' 
 GROUP BY d.deposition_id ORDER BY d.folio_start ASC
 LIMIT 0, 20

如有任何帮助或指导,我们将不胜感激!

沉积表:

CREATE TABLE IF NOT EXISTS `deposition` (
  `deposition_id` varchar(11) NOT NULL default '',
  `manuscript_number` int(10) NOT NULL default '0',
  `folio_start` varchar(4) NOT NULL default '0',
  `folio_end` varchar(4) default '0',
  `page` int(4) default NULL,
  `deposition_type_id` int(10) NOT NULL default '0',
  `comments` varchar(255) default '',
  `title` varchar(255) default NULL,
  PRIMARY KEY  (`deposition_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

日期表

CREATE TABLE IF NOT EXISTS `date` (
  `deposition_id` varchar(11) NOT NULL default '',
  `day` int(2) default NULL,
  `month` int(2) default NULL,
  `year` int(4) default NULL,
  PRIMARY KEY  (`deposition_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

人物类型

CREATE TABLE IF NOT EXISTS `person_type` (
  `person_type_id` int(10) NOT NULL auto_increment,
  `person_type_desc` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`person_type_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=59 ;

最佳答案

似乎您想为每个证词选择一个人、地点等。

您编写的查询将返回给您这个,但不能保证返回哪个,查询效率低下。

试试这个:

SELECT  d.title, d.deposition_id, d.folio_start, d.folio_end, pl.place_id, p.surname, p.forename, p.person_type_id, pt.person_type_desc, p.age, d.manuscript_number, dt.day, dt.month, dt.year, plc.county_id, c.county_desc
FROM    deposition d
LEFT JOIN
        person p
ON      p.id = 
        (
        SELECT  id
        FROM    person pi
        WHERE   pi.deposition_id = d.deposition_id
        ORDER BY
                pi.deposition_id, pi.id
        LIMIT 1
        )
LEFT JOIN
        place_link AS pl
ON      pl.id = 
        (
        SELECT  id
        FROM    place_link AS pli
        WHERE   pli.deposition_id = d.deposition_id
        ORDER BY
                pli.deposition_id, pi.id
        LIMIT 1
        )
LEFT JOIN
        date AS dt
ON      dt.id = 
        (
        SELECT  id
        FROM    date AS dti
        WHERE   dti.deposition_id = d.deposition_id
        ORDER BY
                dti.deposition_id, pi.id
        LIMIT 1
        )
LEFT JOIN
        place AS plc
ON      plc.place_id = pl.place_id 
LEFT JOIN
        county AS c
ON      c.county_id = plc.county_id
WHERE   d.manuscript_number = '840' 
ORDER BY
        d.manuscript_number, d.folio_start
LIMIT   20

deposition (manuscript_number, folio_start) 上创建一个索引以使其快速运行

同时在 personplace_linkdate(deposition_id, id) 上创建复合索引。

关于php - MySQL Left Join、Group By、Order By、Limit = 糟糕的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3948341/

相关文章:

mysql - 是否存在始终返回零结果的 SQL 查询?

database - 用于转储数据库的 bash 脚本

php - 复选框和检查Datatable Jquery PHP Mysql中的所有功能

php - 通过 Ajax 检索/传递日期和选项数据到数据库

mysql - 是否可以将 2 个具有重复数据的 View 连接起来?

mysql - 带有附加表的三向内连接

php - 使用php将mysql表合并到一个表中

php - 先更新或删除,然后插入

php - 在 PHP 中将数据库列值总和设置为单个变量

asp.net - 设置 Orchard 开发工作区