2016-05-09 3 views
1

Привет, мне нужна помощь в оптимизации запроса для больших записей базы данных выше 1 Миллионы. Текущий запрос выполняется 27-30 секунд.Оптимизация запросов для большой базы данных

SELECT SQL_CALC_FOUND_ROWS 
candidate.candidate_id AS candidateID, 
candidate.candidate_id AS exportID, 
candidate.is_hot AS isHot, 
candidate.date_modified AS dateModifiedSort, 
candidate.date_created AS dateCreatedSort, 
candidate.first_name AS firstName, 
candidate.last_name AS lastName, 
candidate.city AS city, 
candidate.state AS state, 
candidate.key_skills AS keySkills, 
owner_user.first_name AS ownerFirstName, 
owner_user.last_name AS ownerLastName, 
CONCAT(owner_user.last_name, 
     owner_user.first_name) AS ownerSort, 
DATE_FORMAT(candidate.date_created, '%m-%d-%y') AS dateCreated, 
DATE_FORMAT(candidate.date_modified, '%m-%d-%y') AS dateModified, 
candidate.email2 AS email2 FROM 
candidate 
    LEFT JOIN 
user AS owner_user ON candidate.owner = owner_user.user_id 
    LEFT JOIN 
saved_list_entry ON saved_list_entry.data_item_type = 100 
    AND saved_list_entry.data_item_id = candidate.candidate_id WHERE 
is_active = 1 GROUP BY candidate.candidate_id ORDER BY dateModifiedSort 
DESC LIMIT 0 , 15 

Есть ли способ уменьшить время выполнения запроса. Я также добавил индекс в таблицы, но он не работает нормально.

Indexes

+0

показывают индекс у вас есть на таблицах .. – scaisEdge

+0

Я добавил скриншот индексов. – VipinS

+0

Можете ли вы также дать нам результат инструкции объяснения для запроса ..? @VipinS –

ответ

1

Я изменил изменил псевдоним таблицы в запросе ниже, используйте этот Это должно решить вашу проблему

SELECT SQL_CALC_FOUND_ROWS 
candidate.candidate_id AS candidateID, 
candidate.candidate_id AS exportID, 
candidate.is_hot AS isHot, 
candidate.date_modified AS dateModifiedSort, 
candidate.date_created AS dateCreatedSort, 
candidate.first_name AS firstName, 
candidate.last_name AS lastName, 
candidate.city AS city, 
candidate.state AS state, 
candidate.key_skills AS keySkills, 
user.first_name AS ownerFirstName, 
user.last_name AS ownerLastName, 
CONCAT(user.last_name, 
     user.first_name) AS ownerSort, 
DATE_FORMAT(candidate.date_created, '%m-%d-%y') AS dateCreated, 
DATE_FORMAT(candidate.date_modified, '%m-%d-%y') AS dateModified, 
candidate.email2 AS email2 FROM 
candidate 
    LEFT JOIN 
user ON candidate.owner = user.user_id 
    LEFT JOIN 
saved_list_entry ON saved_list_entry.data_item_type = 100 
    AND saved_list_entry.data_item_id = candidate.candidate_id WHERE 
is_active = 1 GROUP BY candidate.candidate_id ORDER BY dateModifiedSort 
DESC LIMIT 0 , 15 

используйте следующие запросы для создания индексов для условий соединения

create index index_user user(user_id); 

create index index_saved_list_entry saved_list_entry(data_item_type,data_item_id); 

create index index_candidate candidate(is_active,candidate_id,dateModifiedSort); 
+0

Ниже приведен запрос на создание индекса с указанием ошибки – VipinS

+0

Вышеприведенный запрос занимает 51 секунду после создания индексов. – VipinS

+0

@ VipinS делают шаги сейчас. он должен хорошо работать сейчас –

1

Вы используете шаблон запроса

 SELECT a vast bunch of stuff 
     FROM a complex assembly of JOIN operations 
     ORDER BY some variable DESC 
     LIMIT 0,small number 

Это по своей сути неэффективна: удовлетворить запрос сервер MySQL должен построить огромный набор результатов, то он должен сортировать все это, то он берет первые пятнадцать строк и отбрасывает остальные.

Чтобы сделать это более эффективным, вам нужно отсортировать меньшее количество материалов. Вот как это сделать. Похоже, вы хотите найти последних измененных пятнадцати кандидатов. Этот запрос будет довольно дешево получить идентификаторы этих кандидатов. Он использует один из ваших индексов.

    SELECT candidate_id 
        FROM candidate 
        ORDER BY date_modified DESC 
        LIMIT 0, 15 

Затем вы можете использовать это как подзапрос в своем основном запросе. Добавить такой пункт:

WHERE candidate.candidate_id IN (
        SELECT candidate_id 
        FROM candidate 
        ORDER BY date_modified DESC 
        LIMIT 0, 15) 

на ваш запрос в соответствующем месте.

Обратите внимание, что вы используете nonstandard and potentially harmful MySQL specific extension to GROUP BY. Ваш запрос работает, но если у кандидата более одного владельца, он будет возвращать только один после его случайного выбора.

Наконец, вы, кажется, разместили индексы с одним столбцом на многих столбцах в своей большой таблице. Это пресловутый антипаттерн SQL: все эти индексы замедляют операции INSERT и UPDATE, и большинство из них, вероятно, не направлено на ускорение запроса. Конечно, для этого запроса единственными полезными индексами являются те, которые указаны на date_modified и первичный ключ.

Многие сложные запросы удовлетворяются наилучшим образом с использованием определенных индексов с несколькими столбцами. Куча индексов с одним столбцом не помогает подобным запросам.

+0

Привет, Олли, могу ли я удалить другие индексы, кроме date_modified? не получив большой идеи. – VipinS

1

Во-первых, кандидат, я подозреваю, что это всегда одна запись по идентификатору, так почему вы делаете GROUP BY вне меня, что может быть удалено и немного улучшить.

Во-вторых, вы делаете соединение слева с таблицей «saved_list_entry», но на самом деле не вынимаете из него какие-либо столбцы, поэтому это, вероятно, можно полностью удалить.

В-третьих, из рассмотрения GROUP BY быть больше не применимо, я хотел бы предложить обновить свои показатели, как:

table    index 
CANDIDATE   (is_active, date_modified, candidate_id, owner) 
user    (user_id) 
saved_list_entry (data_item_id, data_item_type) 

Поскольку ваш заказ по дате изменения в порядке убывания, имеющие ИТ во втором положении к is_active (где условие), он будет пахать через ваши первые 15 быстро. Тем не менее, ваш SQL_CALC_FOUND_ROWS все равно придется вспахивать все остальные квалификационные, но набор результатов будет предварительно упорядочен по индексу для соответствия.

SELECT SQL_CALC_FOUND_ROWS 
     c.candidate_id AS candidateID, 
     c.candidate_id AS exportID, 
     c.is_hot AS isHot, 
     c.date_modified AS dateModifiedSort, 
     c.date_created AS dateCreatedSort, 
     c.first_name AS firstName, 
     c.last_name AS lastName, 
     c.city AS city, 
     c.state AS state, 
     c.key_skills AS keySkills, 
     u.first_name AS ownerFirstName, 
     u.last_name AS ownerLastName, 
     CONCAT(u.last_name, u.first_name) AS ownerSort, 
     DATE_FORMAT(c.date_created, '%m-%d-%y') AS dateCreated, 
     DATE_FORMAT(c.date_modified, '%m-%d-%y') AS dateModified, 
     c.email2 AS email2 
    FROM 
     candidate c 
     LEFT JOIN user u 
      ON c.owner = u.user_id 
     LEFT JOIN saved_list_entry s 
      ON c.candidate_id = s.data_item_id 
      AND s.data_item_type = 100 
    WHERE 
     c.is_active = 1 
    GROUP BY 
     c.candidate_id 
    ORDER BY  
     c.date_modified DESC 
    LIMIT 
     0, 15 
1
  1. Избавьтесь от saved_list_entry, он ничего не добавляет.

  2. Задержка присоединения к user. Это позволит вам избавиться от GROUP BY, что добавляет кучу времени и, возможно, раздувает значение FOUND_ROWS().

Что-то вроде:

SELECT c2.*, 
     ou.first_name AS ownerFirstName, 
     ou.last_name AS ownerLastName, 
     CONCAT(ou.last_name, ou.first_name) AS ownerSort, 
    FROM 
     (SELECT SQL_CALC_FOUND_ROWS 
       c.candidate_id AS candidateID, c.candidate_id AS exportID, 
       c.is_hot AS isHot, c.date_modified AS dateModifiedSort, 
       c.date_created AS dateCreatedSort, c.first_name AS firstName, 
       c.last_name AS lastName, c.city AS city, c.state AS state, 
       c.key_skills AS keySkills, 
       DATE_FORMAT(c.date_created, '%m-%d-%y') AS dateCreated, 
       DATE_FORMAT(c.date_modified, '%m-%d-%y') AS dateModified, 
       c.email2 AS email2 
      FROM candidate AS c 
      WHERE is_active = 1 
      GROUP BY c.candidate_id 
      ORDER BY c.date_modified DESC -- note change here 
      LIMIT 0 , 15 
    ) AS c2 
    LEFT JOIN user AS ou ON c2.owner = ou.user_id; 

(я перепутала порядок столбцов, но вы можете это исправить.)

требуется индекс:

candidate: INDEX(is_active, candidate_id, date_modified) 
Смежные вопросы