Возможный вопрос по индексированию?Я могу увеличить скорость запроса? - PullRequest
0 голосов
/ 22 декабря 2018

У меня есть таблица с несколькими миллионами строк, и запрос, который я выполняю, начинает тормозить (все больше данных поступает в него каждый день).Я просто непритязательный веб-разработчик, поэтому я немного запутался, когда дело доходит до задач, связанных с базой данных.Я подозреваю, что пара индексов исправит это, или, возможно, некоторые запросы будут переписаны, но надеялся, что кто-то укажет мне правильное направление.Вот запрос:

   SELECT 
       impressionreport.sitecode AS site, impressionreport.advertisername AS advertiser, impressionreport.mediafilename AS filename,
       SUM(impressionreport.mediafileplays) AS totalplays, SUM(impressionreport.views) AS totalviewers, SUM(impressionreport.impressions) AS totalimpressions, 
       SUM(CASE WHEN impressionreport.gender LIKE 'male' THEN impressionreport.views ELSE 0 END) AS totalmale, 
       SUM(CASE WHEN impressionreport.gender LIKE 'female' THEN impressionreport.views ELSE 0 END) AS totalfemale, 
       SUM(CASE WHEN impressionreport.gender LIKE 'female' AND agegroup.name LIKE 'young' THEN impressionreport.views ELSE 0 END) AS femaleyoung, 
       SUM(CASE WHEN impressionreport.gender LIKE 'female' AND agegroup.name LIKE 'young adult' THEN impressionreport.views ELSE 0 END) AS femaleyoungadult, 
       SUM(CASE WHEN impressionreport.gender LIKE 'female' AND agegroup.name LIKE 'adult' THEN impressionreport.views ELSE 0 END) AS femaleadult, 
       SUM(CASE WHEN impressionreport.gender LIKE 'female' AND agegroup.name LIKE 'senior' THEN impressionreport.views ELSE 0 END) AS femalesenior, 
       SUM(CASE WHEN impressionreport.gender LIKE 'male' AND agegroup.name LIKE 'young' THEN impressionreport.views ELSE 0 END) AS maleyoung, 
       SUM(CASE WHEN impressionreport.gender LIKE 'male' AND agegroup.name LIKE 'young adult' THEN impressionreport.views ELSE 0 END) AS maleyoungadult, 
       SUM(CASE WHEN impressionreport.gender LIKE 'male' AND agegroup.name LIKE 'adult' THEN impressionreport.views ELSE 0 END) AS maleadult, 
       SUM(CASE WHEN impressionreport.gender LIKE 'male' AND agegroup.name LIKE 'senior' THEN impressionreport.views ELSE 0 END) AS malesenior 
   FROM impressionreport 
   LEFT JOIN agegroup ON impressionreport.age >= agegroup.min AND impressionreport.age <= agegroup.max 
   WHERE 
       impressionreport.datelocal >= '5-1-2018' AND
       impressionreport.datelocal < '5-15-2018' AND
       impressionreport.network LIKE '%' AND
       impressionreport.sitecode LIKE '%' AND
       impressionreport.devicename LIKE '%' AND
       impressionreport.advertisername LIKE '%' AND
       impressionreport.mediafilename LIKE '%'
   GROUP BY impressionreport.sitecode, impressionreport.advertisername, impressionreport.mediafilename
   ORDER BY impressionreport.sitecode, impressionreport.advertisername, impressionreport.mediafilename

Существуют индексы для datelocal, devicename, кода сайта, имени рекламодателя, mediafilename, пола, возраста, сети (все btree).

EDIT:

GroupAggregate (стоимость = 197785.58..223336.77 строк = 533798 ширина = 161) (фактическое время = 3789.770..5819.410 строк = 4577 циклов = 1) Ключ группы: impressionreport.sitecode, impressionreport.advertisername, impressionreport.mediafilename ->Сортировка (стоимость = 197785.58..198469.86 строк = 1368560 ширина = 103) (фактическое время = 3789.651..4450.374 строк = 1384106 циклов = 1) Ключ сортировки: impressionreport.sitecode, impressionreport.advertisername, impressionreport.mediafilename Метод сортировки: внешний диск слияния: 119504kB -> Соединение с вложенным циклом слева (стоимость = 0,09,116428,54 строки = 1368560 ширина = 103) (фактическое время = 0,029.,1485,883 строки = 1384106 петли = 1) Фильтр объединения: ((impressionreport.age> = agegroup.min) И (impressionreport.age <= agegroup.max)) Строки, удаленные фильтром соединения: 4885607 -> Сканирование индекса с использованием impressionreport_datelocal_index на impressionreport (cost = 0.09..91793.44 строки = 1368560 ширина = 75) (фактическое время = 0.020..443.316 строк = 1384106 циклов = 1) Индекс Cond: ((datelocal> = '2018-05-01 00:00:00' ::метка времени без часового пояса) И (datelocal <'2018-05-15 00:00:00' :: метка времени без часового пояса)) -> Материализация (стоимость = 0,00..1.02 строк = 4 ширины = 40) (фактическое время =0.000..0.000 строк = 4 цикла = 1384106) -> Seq Scan для возрастной группы (стоимость = 0.00..1.01 строк = 4 ширины = 40) (фактическое время = 0.004..0.005 строк = 4 цикла = 1) Время планирования: 0.270мс Время выполнения: 5838,433 мс

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

-> Сортировка (стоимость = 197785.58..198469.86 строк = 1368560 ширина = 103) ( фактическое время = 3789.651..4450.374 строк = 1384106 циклов = 1) Ключ сортировки: impressionreport.sitecode, impressionreport.Имя рекламодателя, impressionreport.mediafilename Метод сортировки: внешнее объединение Диск: 119504 КБ

3789.651..4450.374 означает, что для завершения этой части в первой строке требуется 3789 мс, а для всех строк - 4450 мсзапрос.

Итак, самая медленная часть - это сортировка, и она медленная, потому что она решила выполнить сортировку на диске.Вероятно, это связано с тем, что для этого требуется немного work_mem

Попробуйте настроить postgresql.conf с помощью https://pgtune.leopard.in.ua, просто введите количество оперативной памяти и нажмите «Генерировать»

0 голосов
/ 22 декабря 2018

Попробуйте индекс на impressionreport (datelocal, sitecode, advertisername, mediafilename) (составной, т. Е. Один индекс для полного списка столбцов, а не один для каждого столбца).

Проверьте план выполнения, чтобы убедиться, что индекс выбран.


Редактировать:

Я был не прав насчет LIKE с.Я упустил возможность фильтрации datelocal перед проверкой LIKE с, даже если они не оптимизированы.

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