Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL огромни таблици JOIN прави базата данни колапс

300k редове не са огромна таблица. Често виждаме 300 милиона таблици с редове.

Най-големият проблем с вашата заявка е, че използвате корелирана подзаявка, така че тя трябва да изпълни повторно подзаявката за всеки ред във външната заявка.

Често се случва да не е необходимо да правите всичко вашата работа в един SQL оператор. Разбиването му на няколко по-прости SQL оператора има предимства:

  • По-лесно за кодиране.
  • По-лесен за оптимизиране.
  • По-лесно отстраняване на грешки.
  • По-лесно за четене.
  • По-лесно за поддръжка, ако/когато трябва да внедрите нови изисквания.

Брой покупки

SELECT customer, COUNT(sale) AS number_of_purchases
FROM sales 
GROUP BY customer;

Индекс за продажби (клиент, продажба) би бил най-подходящ за тази заявка.

Стойност на последната покупка

Това е greatest-n-per-group проблем, който се появява често.

SELECT a.customer, a.sale as max_sale
FROM sales a
LEFT OUTER JOIN sales b
 ON a.customer=b.customer AND a.dates < b.dates
WHERE b.customer IS NULL;

С други думи, опитайте се да съпоставите ред a към хипотетичен ред b който има същия клиент и по-голяма дата. Ако не бъде намерен такъв ред, тогава a трябва да има най-добрата дата за този клиент.

Индекс за продажби (клиент, дати, разпродажба) би бил най-подходящ за тази заявка.

Ако може да имате повече от една продажба за клиент на тази най-добра дата, тази заявка ще върне повече от един ред на клиент. Ще трябва да намерите друга колона, за да развалите равенството. Ако използвате първичен ключ с автоматично нарастване, той е подходящ като решение, тъй като е гарантирано уникален и има тенденция да се увеличава хронологично.

SELECT a.customer, a.sale as max_sale
FROM sales a
LEFT OUTER JOIN sales b
 ON a.customer=b.customer AND (a.dates < b.dates OR a.dates = b.dates and a.id < b.id)
WHERE b.customer IS NULL;

Обща сума на покупките, когато има положителна стойност

SELECT customer, SUM(sale) AS total_purchases
FROM sales
WHERE sale > 0
GROUP BY customer;

Индекс за продажби (клиент, продажба) би бил най-подходящ за тази заявка.

Трябва да обмислите използването на NULL за означаване на липсваща продажна стойност вместо -1. Агрегираните функции като SUM() и COUNT() игнорират NULL, така че не е нужно да използвате клауза WHERE, за да изключите редове с продажба <0.

Re:Вашият коментар

Петте най-добри клиенти за Q4 2012

SELECT customer, SUM(sale) AS total_purchases
FROM sales
WHERE (year, quarter) = (2012, 4) AND sale > 0
GROUP BY customer
ORDER BY total_purchases DESC
LIMIT 5;

Бих искал да го тествам спрямо реални данни, но вярвам, че индексът на продажбите (година, тримесечие, клиент, продажба) би бил най-подходящ за тази заявка.

Последна покупка за клиенти с общ брой покупки> 5

SELECT a.customer, a.sale as max_sale
FROM sales a
INNER JOIN sales c ON a.customer=c.customer
LEFT OUTER JOIN sales b
 ON a.customer=b.customer AND (a.dates < b.dates OR a.dates = b.dates and a.id < b.id)
WHERE b.customer IS NULL
GROUP BY a.id
HAVING COUNT(*) > 5;

Както в другата заявка за най-големи n-на-група по-горе, индексът за продажби (клиент, дати, разпродажба) би бил най-подходящ за тази заявка. Вероятно не може да оптимизира както присъединяването, така и групата, така че това ще доведе до временна таблица. Но поне ще направи само една временна таблица вместо много.

Тези заявки са достатъчно сложни. Не трябва да се опитвате да напишете една единствена SQL заявка, която може да даде всички от тези резултати. Спомнете си класическия цитат от Браян Керниган:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Грешка в MySql:Не може да се актуализира таблицата в съхранената функция/тригера, защото вече се използва от израз, който е извикал тази съхранена функция/тригер

  2. Оптимизиране на MySQL за ALTER TABLE на InnoDB

  3. Ред на оценка на изрази и присвояване на променливи в MySQL UNIONs

  4. Как да се показват записи на база данни в изгледа, без да се повтаря поле?

  5. Как да кеширате обекти, създадени от MySQL база данни