Эффективный дизайн SQL-запросов - PullRequest
1 голос
/ 23 августа 2011

Что обычно считается наиболее эффективным способом выполнения этого типа запроса?

У нас есть база данных лабораторных данных за 10 лет, и мы хотели бы выбрать данные о производительности для различных испытаний. Этот запрос, например, выберет количество часов, потраченных на тестирование, и рассчитает среднее время выполнения заказа, и позволит нам построить спарклайн в среднем по TAT в день.

Скажем, у нас есть 100 имен тестов. Допустимо ли с точки зрения производительности повторять имена тестов в цикле и запускать этот запрос один раз за цикл? Или есть более эффективный способ?

SELECT 
  Date_Authorised_Index.Date_Authorised
  , Result_Set.Date_Booked_In
  , avg(DATEDIFF('hh',Result_Set.Date_Time_Booked_In,Result_Set.Date_Time_Authorised)) as HrsIn
  , count(Date_Authorised_Index.Date_Authorised) as numbers
  , Date_Authorised_Index.Registration_Number
  , Date_Authorised_Index.Request_Row_ID
  , Date_Authorised_Index.Specimen_Number
  , Result_Set.Authorised_By
  , Result_Set.Namespace
  , Result_Set.Set_Code
  , Result_Set.Date_Time_Authorised
  , Request.Date_Time_Received
  , Request.Location 
FROM 
  Date_Authorised_Index Date_Authorised_Index
  , Result_Set Result_Set
  , Request 
WHERE 
  Date_Authorised_Index.Date_Authorised = Result_Set.Date_Authorised 
  AND Date_Authorised_Index.Request_Row_ID = Request.Request_Row_ID
  AND Date_Authorised_Index.Request_Row_ID = Result_Set.Request_Row_ID 
  AND (Date_Authorised_Index.Discipline='C') AND Result_Set.Set_Code=? 
GROUP BY 
  Result_Set.Date_Booked_In

1 Ответ

0 голосов
/ 23 августа 2011

Для начала я бы переписал этот запрос, чтобы он использовал явный синтаксис объединения.
Также, несмотря на то, что MySQL не заставляет вас пересчитывать каждый неагрегированный столбец в предложении group by, это не значит, что это хорошо.
Если Result_Set.Date_Booked_In не уникально идентифицирует строку, вы выбираете случайные значения из множества строк.

SELECT 
  dai.Date_Authorised
  , rs.Date_Booked_In
  , avg(DATEDIFF('hh',rs.Date_Time_Booked_In,rs.Date_Time_Authorised)) as HrsIn
  , count(dai.Date_Authorised) as numbers
  , dai.Registration_Number
  , dai.Request_Row_ID
  , dai.Specimen_Number
  , rs.Authorised_By
  , rs.Namespace
  , rs.Set_Code
  , rs.Date_Time_Authorised
  , r.Date_Time_Received
  , r.Location 
FROM 
  Date_Authorised_Index dai    
INNER JOIN Result_Set rs ON (dai.Date_Authorised = rs.Date_Authorised
                         AND dai.Request_Row_ID = rs.Request_Row_ID)
INNER JOIN Request R ON (dai.Request_Row_ID = r.Request_Row_ID)
WHERE 
  (dai.Discipline= 'C') AND rs.Set_Code=? 
GROUP BY 
  rs.Date_Booked_In

Если вы хотите выбрать 100 строк за один раз, просто создайте новую таблицу с кодами set_codes, которые вы хотите выбрать, и присоединитесь к ней.
Убедитесь, что вы проиндексировали поле sc.set_code(или еще лучше сделайте его первичным ключом)

SELECT lots_of_columns
FROM table1 as dai
INNER JOIN table2 as rs ON (what you joined on before)
INNER JOIN table3 as r ON (same here)
INNER JOIN Setcodes as sc ON (sc.Set_code = rs.SetCode)  <<-- extra join.
WHERE 
  dai.discipline = 'C'
GROUP BY  rs.Date_Booked_In

Или вы даже можете использовать `IN (...), как показано ниже, хотя это, вероятно, будет медленнее, чем соединение.

SELECT lots_of_columns
FROM table1 as dai
INNER JOIN table2 as rs ON (what you joined on before)
INNER JOIN table3 as r ON (same here)
WHERE 
  dai.discipline = 'C' AND rs.Set_Code IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
GROUP BY  rs.Date_Booked_In
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...