MySQL оптимизированная производительность для двух больших таблиц с одинаковым индексом - PullRequest
0 голосов
/ 17 июня 2020

У меня есть две таблицы с огромным количеством данных в них (~ 1,8 мил в основной, ~ 1,2 мил во вторичной), а именно:

subscriber_table (id, name, email, country , account_status, ...) subscriber_payment_table (id, subscriber_id, payment_type, payment_credential)

Моя конечная цель - иметь таблицу, содержащую всех пользователей и их таблицы платежей (null, если не существует), до вчера , и с account_status = 1 (active)

Не у всех подписчиков есть соответствующий subscriber_payment, поэтому использование INNER JOIN не является жизнеспособным вариантом, а использование LEFT JOIN приводит к тому, что я получаю SQL тайм-аут моего запроса через 2 часа после больших усилий по обработке.

SELECT 
    `subscribers`.`id` AS `id`,
    `subscribers`.`email` AS `email`,
    `subscribers`.`name` AS `name`,
    `subscribers`.`geoloc_country` AS `country`,

    `subscribers_payment`.`payment_type` AS `paymentType`,
    `subscribers_payment`.`payment_credential` AS `paymentCredential`

    `subscribers`.`create_datetime` AS `createdAt`
FROM
    `subscribers`
LEFT JOIN 
    `subscribers_payment` ON (`subscribers_payment`.`subscriberId` = `subscribers`.`id`)
WHERE
    `subscribers`.`account_status` = 1
    AND DATE_FORMAT(CAST(`subscribers`.`create_datetime` AS DATE), '%Y-%m-%d') < curdate())

Как уже упоминалось, этот запрос занимает слишком много времени и заканчивается тайм-аутом и не работает. Я также рассматривал возможность использования UNION между «Все подписчики» и «Подписчики с оплатой».

(
SELECT 
    `subscribers`.`id` AS `id`,
    `subscribers`.`email` AS `email`,
    `subscribers`.`name` AS `name`,
    `subscribers`.`geoloc_country` AS `country`,

    null AS `paymentType`,
    null AS `paymentCredential`

    `subscribers`.`create_datetime` AS `createdAt`
FROM
    `subscribers`
WHERE
    `subscribers`.`account_status` = 1
    AND DATE_FORMAT(CAST(`subscribers`.`create_datetime` AS DATE), '%Y-%m-%d') < curdate()))
UNION
(
SELECT 
    `subscribers`.`id` AS `id`,
    `subscribers`.`email` AS `email`,
    `subscribers`.`name` AS `name`,
    `subscribers`.`geoloc_country` AS `country`,

    `subscribers_payment`.`payment_type` AS `paymentType`,
    `subscribers_payment`.`payment_credential` AS `paymentCredential`

    `subscribers`.`create_datetime` AS `createdAt`
FROM
    `subscribers`
INNERJOIN 
    `subscribers_payment` ON (`subscribers_payment`.`subscriberId` = `subscribers`.`id`)
WHERE
    `subscribers`.`account_status` = 1
    AND DATE_FORMAT(CAST(`subscribers`.`create_datetime` AS DATE), '%Y-%m-%d') < curdate()))

Проблема с этой текущей реализацией заключается в том, что я получаю повторяющиеся запросы (я использую UNION, но он не группирует мои результаты вместе и не удаляет неотличимые значения, потому что у меня другое значение в столбцах paymentType и paymentCredential)

Этот запрос выполняется примерно за ~ 2 минуты, поэтому для меня посильнее. Мне просто нужно удалить повторяющиеся записи ... если здесь нет более разумного варианта

Отказ от ответственности: мы используем таблицы MyISAM, поэтому наличие внешних ключей для ускорения запросов - это не- go.

1 Ответ

0 голосов
/ 17 июня 2020

Для этого запроса:

SELECT  . . . 
FROM subscribers s LEFT JOIN
     subscribers_payment sp
     ON sp.subscriberId = s.id
WHERE s.account_status = 1 AND
      s.create_datetime < curdate();

Затем вам нужен индекс на subscribers(account_status, create_datetime, id) и subscribers_payment(subscriberId).

Я предполагаю, что индекс на subscriber_payment отсутствует , что объясняет проблемы с производительностью.

Примечания:

  • Используйте псевдонимы таблиц - они упрощают запись и чтение запроса.
  • В этом не должно быть необходимости для преобразования datetime в строку для целей сравнения.
  • Нет необходимости использовать обратные кавычки для всех идентификаторов. Они просто затрудняют написание и чтение запроса.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...