Помощь эксперта Sybase: проблемы с производительностью по группам - PullRequest
2 голосов
/ 02 апреля 2011

Эй, у меня есть следующие таблицы и SQL:

T1: ID, col2, col3 - PK (ID) - 23 миллиона строк

T2: ID, col2, col3 - PK (ID) - 23 миллиона строк

T3: ID, имя, значение - PK (ID, имя) -66 миллионов строк

1) Приведенный ниже sql очень быстро возвращает набор результатов из 10 000 строк, без проблем.

select top 10000 T1.col2, T2.col2, T3.name, T4.value 
from T1, T2, T3  
where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ') 
and T2.col1 = 'SOMEVALUE'

2) Ниже sql взял навсегда.

select top 10000 T1.col2, T2.col2, 

ABC  = min(case when T3.name='ABC ' then T3.value end)  
XYZ  = min(case when T3.name='XYZ ' then T3.value end)  

from T1, T2, T3  

where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ')
and T2.col1 = 'SOMEVALUE'

group by T1.col2, T2.col2, 

Единственное различие в showplan между этими двумя запросами - ниже для запроса 2). Я не понимаю это на 100%, выбирает ли он ВЕСЬ набор результатов БЕЗ 10000 во временную таблицу, а затем создает группу на нем? поэтому медленно?

STEP 1
    The type of query is SELECT (into Worktable1).
    GROUP BY
    Evaluate Grouped MINIMUM AGGREGATE.

    FROM TABLE ...etc..

    TO TABLE
        Worktable1.

STEP 2
    The type of query is SELECT.

    FROM TABLE
        Worktable1.
    Nested iteration.
    Table Scan.
    Forward scan.
    Positioning at start of table.
    Using I/O Size 16 Kbytes for data pages.
    With MRU Buffer Replacement Strategy for data pages.

Мой вопрос

1) Почему запрос 2) такой медленный

2) Как исправить, сохранив логику запроса такой же, и желательно ограничить ее только одним выбором SQL, как и раньше.

спасибо

1 Ответ

1 голос
/ 02 апреля 2011

Хотя, возможно, общий ответ, я бы сказал, чтобы поставить индекс для столбцов, по которым вы группируете.

Редактировать / Пересмотреть: Вот моя теория после пересмотрапроблема.Оператор SELECT в запросе всегда является последней выполненной строкой.Это имеет смысл, поскольку именно оператор извлекает нужные значения из набора данных, указанного ниже.В вашем запросе весь набор данных (миллионы записей) будет оцениваться по указанному вами выражению значения MIN.Во всем наборе данных будут вызываться две отдельные функции, поскольку в операторе select вы указали два столбца MIN. После набор данных отфильтрован и определены столбцы MIN, затем будут выбраны верхние 10000 строк.

В двух словах, вы выполняете две математические функции для миллионов записей.Это займет значительное время, особенно без индексов.

Решение для вас - использовать производную таблицу.Я не скомпилировал код ниже, но это что-то близкое к тому, что вы бы использовали.Он будет принимать только минимальные значения 10000 записей, а не весь набор данных.

Т.е.

    Select my_derived_table.t1col2, my_derived_table.t2col2,
    ABC  = min(case when my_derived_table.t3name ='ABC ' then my_derived_table.t3value end),  
    XYZ  = min(case when my_derived_table.t3name='XYZ ' then my_derived_table.t3value end)
    FROM
      (Select top 10000 T1.col2 as t1col2, 
              T2.col2 as t2col2, 
              t3.name as t3name, 
              t3.value as t3.value
       from T1, T2, T3
       where T1.ID = T2.ID 
         and T1.ID *= T3.ID 
         and T3.name in ('ABC','XYZ')
         and T2.col1 = 'SOMEVALUE') my_derived_table
group by my_derived_table.t1col2, my_derived_table.t2col2
...