Mysql Присоединяйтесь к спектаклю MongoDB, Cassandra - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть запрос на соединение, обработка которого занимает много времени.

SELECT
COUNT(c.id)
FROM `customers` AS `c`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`id`
LEFT JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `customers_address` AS `ca` ON `ca`.`id` =            `cx`.`customer_default_address_id`
LEFT JOIN `lytcustomer_tier` AS `ct` ON `cx`.`lyt_customer_tier_id` = `ct`.`id`
WHERE (c.shop_id = '12121') AND ((DATE(cx.last_email_open_date) > '2019-11-08')); 

Это в первую очередь потому, что в таблице "клиенты" есть 2 миллиона записей.

Я мог go в индексирование и т.д. c. Но, что еще важнее, эти 2,5 миллиона могут стать миллиардом записей за 1 день.

Я ищу решения, которые могут повысить производительность. Я подумал о

а) горизонтальной масштабируемости. -: распределите таблицу mysql по разным разделам и запросите счет независимо.

b) используя составные индексы.

c) Мой любимый -: Просто создайте отдельную коллекцию в mongodb или redis, который содержит только счетчик (вывод этого запроса), так как счетчик - только 1 число. это не потребует огромного размера, а также лучшей производительности запросов (вопрос только в том, сколько таких запросов, потому что это увеличит размер новой коллекции)

Ответы [ 2 ]

1 голос
/ 11 апреля 2020
  • Скажите COUNT(*), а не COUNT(c.id)
  • Удалите их; они замедляют запрос, не добавляя ничего, что я вижу:

    LEFT JOIN  `setting` AS `ssh`  ON `c`.`shop_id` = `ssh`.`id`
    LEFT JOIN  `customers_address` AS `ca`  ON `ca`.`id` = `cx`.`customer_default_address_id`
    LEFT JOIN  `lytcustomer_tier` AS `ct`  ON `cx`.`lyt_customer_tier_id` = `ct`.`id`
    
  • DATE(...) делает этот тест не "sargable". Это работает для DATE или DATETIME; и это намного быстрее:

    cx.last_email_open_date > '2019-11-08'
    
  • Подумайте, должно ли это быть >= вместо >.

  • Нужен индекс для shop_id. (Пожалуйста, укажите SHOW CREATE TABLE.)
  • Не используйте LEFT JOIN, когда JOIN будет работать одинаково хорошо.
  • Если customer_extra - это столбцы, которые должны были быть в customer, сейчас самое время их переместить. Это позволит вам использовать этот составной индекс для еще большей производительности:

    INDEX(shop_id, last_email_open_date)   -- in this order
    

С этими изменениями миллиард строк в MySQL вероятно не будет проблемой. Если это так, я могу предложить еще несколько исправлений.

0 голосов
/ 11 апреля 2020

Попробуйте и посмотрите, улучшит ли это производительность:

SELECT
COUNT(c.id)
FROM `customers` AS `c`
INNER JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`id`
LEFT JOIN `customers_address` AS `ca` ON `ca`.`id` =            `cx`.`customer_default_address_id`
LEFT JOIN `lytcustomer_tier` AS `ct` ON `cx`.`lyt_customer_tier_id` = `ct`.`id`
WHERE (c.shop_id = '12121') AND ((DATE(cx.last_email_open_date) > '2019-11-08'));

Как я уже упоминал в комментарии, так как условие AND ((DATE(cx.last_email_open_date) > '2019-11-08'));, уже сделало customers таблицу до INNER JOIN с customer_extra таблицей , вы можете просто изменить его на INNER JOIN customer_extra AS cx ON c.id = cx.customer_id и следовать за ним с другим LEFT JOIN.

INNER JOIN по крайней мере получит первоначальный результат, чтобы вернуть только любого клиента, который имеет значение last_email_open_date на основе того, что было указано.

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