Повышение производительности SQL-запросов - PullRequest
0 голосов
/ 20 июля 2011

Sql:

select distinct DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as Date,
(select count(*) from Raw_Mats A where DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)) as Total,
(select count(*) from Raw_Mats B where DateAdd(Day, DateDiff(Day, 0, B.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) and B.status='Solved') as Delivered,
(select count(*) from Raw_Mats C where DateAdd(Day, DateDiff(Day, 0, C.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) and C.status='Pending') as UnDelivered
from Raw_Mats m where m.Receive_date between '2011-07-01' and '2011-07-21'

Как повысить производительность вышеуказанного запроса. Это займет 44 секунды. хочу сделать это менее чем за 10 секунд

Спасибо

Ответы [ 3 ]

3 голосов
/ 20 июля 2011

У вас есть индекс для Receive_date и status?(не индекс по каждому, вместе взятый)

Также:

  • У вас есть 4 касания в таблице, что означает, что запрос будет масштабироваться как минимум O (4n).С помощью COUNT (CASE) вы можете удалить Delivered и UnDelivered подзапросы
  • Простой подзапрос подсчета также не требуется
  • Вам необходим GROUP BY.ВАШЕ ОТЛИЧИЕ - это обходной путь для этого
  • МЕЖДУ >= и <=, который обычно не подходит для дат со временем

Я использовал подзапрос здесьдля ясности, но это не имеет значения:

select
   DateOnly as Date,
   COUNT(*) AS Total,
   COUNT(CASE WHEN status='Solved' THEN 1 END) AS Delivered,
   COUNT(CASE WHEN status='Pending' THEN 1 END) AS UnDelivered
from
   (
   SELECT
       DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as DateOnly,
       status
   FROM
      Raw_Mats
   WHERE
      Receive_date >= '2011-07-01' AND Receive_date < '2011-07-21'
   ) T
 GROUP BY
   DateOnly

Редактировать, без подзапроса.

Я начал с подзапроса, потому что думал, что он будет более сложным, чем ожидалось, и не потрудился убрать его ...

select
   DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as Date,
   COUNT(*) AS Total,
   COUNT(CASE WHEN status='Solved' THEN 1 END) AS Delivered,
   COUNT(CASE WHEN status='Pending' THEN 1 END) AS UnDelivered
from
   Raw_Mats
WHERE
   Receive_date >= '2011-07-01' AND Receive_date < '2011-07-21'
GROUP BY
   DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)
0 голосов
/ 20 июля 2011

Слишком много подзапросов, человек! Избавьтесь от некоторых из них, и это поможет. Также вы не должны использовать функции с обеих сторон в вашем sqls.

Например:

where DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0)=
              DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) 

В этом конкретном случае движок БД должен пройти все строки, чтобы оценить DateDiff(Day, 0, A.Receive_date) and DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0), а затем сравнить его с правой частью, которая также является функцией! Это просто катастрофа.

Кроме того, у вас есть индексы на Receive_date? Если нет, добавьте его.

0 голосов
/ 20 июля 2011

Разделяй и властвуй: просто попробуйте каждую часть вашего sql как отдельное утверждение, и вы узнаете, какая часть медленная.Если у вас есть подвыборы и функции, есть хороший шанс, что серверу понадобятся временные таблицы для выполнения выбора, если у вас недостаточно памяти (или большой набор данных или настроенный сервер sql для этого), этовременные объекты помещаются на диск, что также замедляет работу.

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