MySQL Left Join, Group By, Order By, Limit = ужасная производительность - PullRequest
3 голосов
/ 16 октября 2010

В настоящее время я разрабатываю приложение, позволяющее пользователям осуществлять поиск в базе данных документов с использованием различных параметров и возвращать набор постраничных результатов. Я строю его на 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;

Person_Type

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 ;

Ответы [ 3 ]

2 голосов
/ 16 октября 2010

Кажется, что вы хотите выбрать одного человека, место и т. Д. Для депонирования.

Написанный вами запрос вернет вам это, но не гарантируется, какой из них он вернет, и запрос неэффективен.

Попробуйте:

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), чтобы это работало быстро

Также создайте составной индекс на (deposition_id, id) на person, place_link и date.

1 голос
/ 16 октября 2010

Низкая производительность почти наверняка связана с отсутствием индексов. Ваша таблица удаления не имеет никаких индексов, и это, вероятно, означает, что другие таблицы, на которые вы ссылаетесь, тоже не имеют никаких индексов. Вы можете начать с добавления индекса в вашу таблицу осаждения. Из оболочки MySQL или phpMyAdmin выполните следующий запрос.

ALTER TABLE deDD ADD INDEX (deposition_id, manuscript_number);

Вы знаете, что находитесь на правильном пути, если запрос выполняется быстрее после добавления индекса. Оттуда вы можете разместить индексы в других таблицах столбцов, на которые есть ссылки. Например, для этой части вашего запроса "LEFT JOIN person AS p ON p.deposition_id = d.deposition_id" вы можете попробовать добавить индекс в таблицу person, используя.

ALTER TABLE person ADD INDEX (deposition_id);

1 голос
/ 16 октября 2010

Вам нужно только LEFT JOIN, если объединенная таблица может не иметь подходящего значения. Возможно ли в вашей схеме базы данных для person не иметь совпадения person_type? Или deposition чтобы не было соответствующей строки в date? A place не соответствует county?

Чтобы любое из этих отношений, которое должно существовать, чтобы результат имел смысл, вы можете изменить LEFT JOIN на INNER JOIN.

Эти столбцы должны иметь индексы (уникальные, если это возможно):

person.deposition_id
date.deposition_id
place_link.deposition_id
place_link.place_id

Стол date выглядит как плохой дизайн; Я не могу придумать причину иметь таблицу дат вместо того, чтобы просто поместить столбец типа date (или datetime) в таблицу deposition. И date - ужасное имя для таблицы, потому что это зарезервированное слово SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...