Вложенный оператор выбора в предложении FROM? Inner Присоединиться к заявлениям? или просто имя таблицы? - PullRequest
1 голос
/ 22 декабря 2011

Я строю запрос, который требует данных из 5 таблиц. В прошлом мне говорили администратор базы данных, что указание списка столбцов вместо получения всех столбцов (*) предпочтительнее с точки зрения производительности / памяти. Мне также сказали, что база данных выполняет операцию JOIN за кулисами, когда в предложении FROM есть список таблиц для создания одной таблицы (или представления).

На данный момент в существующей базе данных очень мало данных, так как мы находимся на начальном этапе. Так что не уверен, что смогу измерить удар производительности на практике. Я не профессионал базы данных. Я могу получить то, что мне нужно. Дилемма есть, по какой цене.

Добавлено: В данный момент я работаю с MS SQL Server 2008 R2.

Мои вопросы:

  1. Есть ли разница в производительности и почему между следующими: а. ВЫБЕРИТЕ ... ОТ tbl1, tbl2, tbl3 и т. Д. Для простоты? (почему-то я чувствую, что это может быть удар по производительности) б. ВЫБРАТЬ ... ОТ tbl1 внутреннего соединения tbl2 в ... внутреннего соединения tbl3 в ... и т. Д. (Будет ли это более явным для сервера и сэкономит на производительности / памяти)? с. SELECT ... FROM (выберите x, y, z из tbl1) как внутреннее соединение t1 ... и т. Д. (Спасет ли это что-нибудь? Или это просто дополнительные операторы select, которые создают больше работы для сервера и для нас)?

  2. Есть ли еще лучший способ сделать это?

Ниже приведены два запроса, которые оба получают часть данных, которые мне нужны. Один включает больше вложенных операторов выбора.

Я прошу прощения, если они не написаны в стандартной форме или беспомощно чрезмерно сложны - надеюсь, вы сможете расшифровать. Я стараюсь максимально их организовывать.

Инсайты также были бы очень полезны. Спасибо за проверку.

5 таблиц: пул устройств, пользователи, поездки, TripTracker и заказ

Запрос 1 (больше операторов select):

SELECT
      username, 
      base.devid devid, 
      tripstatus, 
      stops, 
      stopnumber, 
      [time], 
      [orderstatus], 
      [destaddress]

FROM    
((
 (  SELECT 
           username, 
           devicepool.devid devid,
           groupid
    FROM
           devicepool INNER JOIN users 
           ON devicepool.userid = users.userid 

     WHERE devicepool.groupid = 1
 ) 
 AS [base] 

 INNER JOIN

 (
      SELECT 
              tripid, 
              [status] tripstatus, 
              stops, 
              devid,
              groupid

      FROM 
              trips 
 ) 
 AS [base2]

 ON base.devid = base2.devid AND base2.groupid = base.groupid

 INNER JOIN

 (
     SELECT 
            stopnumber, 
            devid, 
            [time], 
            MAX([time]) OVER (PARTITION BY devid) latesttime 
     FROM 
            TripTracker
 ) 

 AS [tracker] 
 ON tracker.devid = base.devid AND [time] = latesttime)

 INNER JOIN

 (
      SELECT 
            [status] [orderstatus], 
            [address] [destaddress], 
            [tripid], 
            stopnumber orderstopnumber 
      FROM [order]
 ) 
 AS [orders] 

 ON orders.orderstopnumber = tracker.stopnumber)

Запрос 2:

SELECT
      username, 
      base.devid devid, 
      tripstatus, 
      stops, 
      stopnumber, 
      [time], 
      [orderstatus], 
      [destaddress]

FROM    
((
 (  SELECT 
           username, 
           devicepool.devid devid,
           groupid
    FROM
           devicepool INNER JOIN users 
           ON devicepool.userid = users.userid 

     WHERE devicepool.groupid = 1
 ) 
 AS [base] 

 INNER JOIN

     trips

 ON base.devid = trips.devid AND trips.groupid = base.groupid

 INNER JOIN

 (
     SELECT 
            stopnumber, 
            devid, 
            [time], 
            MAX([time]) OVER (PARTITION BY devid) latesttime 
     FROM 
            TripTracker
 ) 

 AS [tracker] 
 ON tracker.devid = base.devid AND [time] = latesttime)

 INNER JOIN

    [order]

 ON [order].stopnumber = tracker.stopnumber)

1 Ответ

5 голосов
/ 22 декабря 2011

Есть ли разница в производительности и почему между следующими: a.ВЫБЕРИТЕ ... ОТ tbl1, tbl2, tbl3 и т. Д. Для простоты?(почему-то я чувствую, что это может быть удар по производительности) б.ВЫБРАТЬ ... ОТ tbl1 внутреннего соединения tbl2 в ... внутреннего соединения tbl3 в ... и т. Д. (Будет ли это более явным для сервера и сэкономит на производительности / памяти)?с.SELECT ... FROM (выберите x, y, z из tbl1) как внутреннее соединение t1 ... и т. Д. (Спасет ли это что-нибудь еще?*

a) и b) должны приводить к одному и тому же плану запросов (хотя это зависит от БД).б) гораздо предпочтительнее по портативности и удобочитаемости, чем а).в) ужасная идея, которая ухудшает читабельность и, если что-нибудь, приведет к ухудшению производительности.Давайте никогда не будем говорить об этом снова.

Есть ли еще лучший способ сделать это?

b) - это стандартный подход.В целом, написание простого ANSI SQL приведет к наилучшей производительности, поскольку позволяет анализатору запросов легко понять, что вы пытаетесь сделать.Попытка перехитрить компилятор с хитростями может работать в данной ситуации, но это не значит, что он все равно будет работать, когда изменяется количество элементов или количество данных, или обновляется ядро ​​базы данных.Поэтому избегайте этого, если только вы не обязаны это делать.

...