Лучший способ оптимизировать SQL для поворота таблицы в Sybase Ase - PullRequest
3 голосов
/ 25 ноября 2010

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

SQL-оператор, который я пытаюсь оптимизировать

select Col1, Col2,
Max(case when TypeId = 1 then ColValue end) as Pivot1,
Max(case when TypeId = 2 then ColValue end) as Pivot2,
Max(case when TypeId = 3 then ColValue end) as Pivot3,
Max(case when TypeId = 4 then ColValue end) as Pivot4,
Max(case when TypeId = 5 then ColValue end) as Pivot5,
Max(case when TypeId = 6 then ColValue end) as Pivot6,
Max(case when TypeId = 7 then ColValue end) as Pivot7,
Max(case when TypeId = 8 then ColValue end) as Pivot8,
Max(case when TypeId = 9 then ColValue end) as Pivot9,
Max(case when TypeId = 10 then ColValue end) as Pivot10,
Max(case when TypeId = 11 then ColValue end) as Pivot11
from RowTable
group by Col1, Col2

ОБНОВЛЕНИЕ: Ниже приведено определение таблицы

CREATE TABLE dbo.RowTable  ( 
    Id                  int NOT NULL,
    Col1                char(8) NOT NULL,
    Col2                tinyint NOT NULL,
    TypeId              int NOT NULL,
    ColValue            datetime NOT NULL,
    CreatedBy           varchar(50) NOT NULL,
    Rowstamp            timestamp NOT NULL 
    )
LOCK DATAROWS
GO
ALTER TABLE dbo.RowTable
    ADD CONSTRAINT ukRowTable
    UNIQUE (Col1, Col2, TypeId)
    WITH max_rows_per_page = 0, reservepagegap = 0

Ответы [ 2 ]

1 голос
/ 28 ноября 2010

Ответ на оригинальный вопрос

1. Производительность с таблицей как есть.
Что ж, прежде чем кто-либо сможет оценить этот код с точки зрения производительности, нам нужен оператор создания таблицы, включая индексы.

  1. Высший класс производительности.
    Поворот - это функция выражения данных, доступных в строках, в столбцах. Если база данных (таблица), скажем, нормирована на 3NF или 5NF, которая ориентирована на строки, то выполнение столбчатых функций на объектах строк будет медленным. Ничего общего с продуктом. Если вам нужен быстрый доступ к столбцам (для Pivoting или любой другой функции столбцов), вам нужны данные в 6NF. Это также делает SQL-запрос, необходимый для выполнения этой задачи, более простым.

    Если разработчик моделей данных подготовил таблицу для поворота (обычно это использование типа хранилища данных; структура факта измерения), то это может быть не правда 6NF, но, по крайней мере, это будет лучше, чем 5NF, и будет проще извлекать сводные значения. Когда я увижу DDL, я смогу определить, что это такое (правда, 6NF; лучше, чем 5NF, но не 6NF). Тогда я могу определить, используете ли вы лучший код, чтобы получить то, что вам нужно.

    Это только медленно или «дорого», когда таблица не в 6NF.

  2. На этом этапе из вашего кода он даже не выглядит как Pivot (используя стандартное значение термина), он выглядит как MAX() различных значений (вызывая результирующий столбец Pivotx не делает его опорным); и вы читаете каждую строку, один раз. То есть у вас процедурное мышление, а не поворотное или ориентированное на множество мышление. Поэтому код, скорее всего, не получит требуемые значения (независимо от того, хорошо он работает или нет, это отдельная проблема).

    Использование вами GROUP BY подтверждает процедурный подход к непроцедурному набору, и это будет медленно (создает рабочие таблицы; оно будет огромным, если ваши данные огромны), и ту же информацию можно получить много быстрее через Размеры. Почему вы не используете таблицы измерений для этой сводной таблицы? Разместите либо DDL для всех таблиц измерений, связанных с этой таблицей, либо для модели данных.

Ответ на комментарий

Я пытаюсь вам помочь, но есть два препятствия. Во-первых, 19 дней между взаимодействиями. Во-вторых, ваш опубликованный SQL не будет работать: для каждой строки он возвращает одинаковые ColValue в 11 столбцах; Я не могу понять цель вашего использования MAX(). Хорошо, MAX() требуется, чтобы превзойти GROUP BY в подчинении. Поэтому я все еще в растерянности относительно того, что вы намереваетесь (не то, что вы кодировали). Запутывание достаточно справедливо, но здесь мы потеряли смысл.

Да, есть более быстрые способы, но мне нужно понять намерение и родительские таблицы (например, есть ли у вас таблица, в которой (Col1, Col2) уникальна? Если это база данных, то таблицы не стоят отдельно, они связаны, и отношения имеют какую-то цель. Я понимаю, что вы не думаете , что они актуальны, но это ограничение привело к тому, что вы разместили код; .

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

<code>[Superceded, refer below]

И, возможно, вы можете дать мне отзыв об этом.

Ответ на обновленный вопрос

Хорошо, теперь у нас есть один ненормализованный стол. Новый набор шагов. Это построенный набор результатов, использующий коррелированные подзапросы, которые возвращают скаляры. Это не перестановка строк против столбцов; это не стандартный кронштейне (поэтому код, предоставленный не является стержнем). Смертельно просто. Возможно, вы захотите изменить заголовок вопроса, потому что люди ищут настоящий Pivot. И да, это будет работать намного лучше (при условии, что ваш DDL является истинным представлением реальных таблиц).

Для ясности, Pivot (аля MS SQL PIVOT функция) - это другое животное. Я могу предоставить уродливый и медленный Pivot для ненормализованной базы данных; или чистый, но медленный Pivot из базы данных 5NF; или чистый и быстрый Pivot из базы данных 6NF. Это не так.

  1. Предположим, что это реляционная база данных. Учитывая предоставленный DDL, будет ParentTable, в котором (Col1, Col2) является уникальным.

  2. Код:

    <code>SELECT  Col1, 
        Col2,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 1 ) as Latest_1,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 2 ) as Latest_2,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 3 ) as Latest_3,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 4 ) as Latest_4,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 5 ) as Latest_5,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 6 ) as Latest_6,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 7 ) as Latest_7,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 8 ) as Latest_8,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 9 ) as Latest_9,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=10 ) as Latest_10,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=11 ) as Latest_11
    FROM ParentTable  OUTER
  3. Если нет ParentTable (т.е. это не реляционная база данных), создайте его на лету с SELECT-INTO или используйте производную таблицу:

    <code>SELECT  Col1, 
        Col2,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 1 ) as Latest_1,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 2 ) as Latest_2,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 3 ) as Latest_3,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 4 ) as Latest_4,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 5 ) as Latest_5,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 6 ) as Latest_6,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 7 ) as Latest_7,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 8 ) as Latest_8,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 9 ) as Latest_9,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=10 ) as Latest_10,
        ( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=11 ) as Latest_11
    FROM (
        SELECT DISTINCT
                Col1,
                Col2
            FROM RowTable
        )  OUTER
  4. Вы можете избавиться от столбца Id в RowTable, это 100% избыточный столбец и индекс, который не имеет смысла.

0 голосов
/ 26 ноября 2010

Поворот является по своей сути дорогостоящей операцией.Я не думаю, что это можно оптимизировать.

...