У меня есть таблица ItemValue , заполненная данными на сервере SQL 2005, работающем в режиме совместимости 2000, который выглядит примерно так (это таблица определяемых пользователем значений):
ID ItemCode FieldID Value
-- ---------- ------- ------
1 abc123 1 D
2 abc123 2 287.23
4 xyz789 1 A
5 xyz789 2 3782.23
6 xyz789 3 23
7 mno456 1 W
9 mno456 3 45
... and so on.
FieldID взято из таблицы ItemField :
ID FieldNumber DataFormatID Description ...
-- ----------- ------------ -----------
1 1 1 Weight class
2 2 4 Cost
3 3 3 Another made up description
. . x xxx
. . x xxx
. . x xxx
x 91 (we have 91 user-defined fields)
Поскольку я не могу PIVOT в режиме 2000, мы застряли в создании уродливого запроса с использованием CASEи GROUP BY, чтобы данные выглядели так, как это должно быть для некоторых унаследованных приложений, а именно:
ItemNumber Field1 Field2 Field3 .... Field51
---------- ------ ------- ------
abc123 D 287.23 NULL
xyz789 A 3782.23 23
mno456 W NULL 45
Вы можете видеть, что нам нужна только эта таблица для отображения значений до 51-го UDF.Вот запрос:
SELECT
iv.ItemNumber,
,MAX(CASE WHEN f.FieldNumber = 1 THEN iv.[Value] ELSE NULL END) [Field1]
,MAX(CASE WHEN f.FieldNumber = 2 THEN iv.[Value] ELSE NULL END) [Field2]
,MAX(CASE WHEN f.FieldNumber = 3 THEN iv.[Value] ELSE NULL END) [Field3]
...
,MAX(CASE WHEN f.FieldNumber = 51 THEN iv.[Value] ELSE NULL END) [Field51]
FROM ItemField f
LEFT JOIN ItemValue iv ON f.ID = iv.FieldID
WHERE f.FieldNumber <= 51
GROUP BY iv.ItemNumber
Когда ограничение FieldNumber равно <= 51, план выполнения выглядит примерно так: </p>
SELECT <== Computer Scalar <== Stream Aggregate <== Sort (Cost: 70%) <== Hash Match <== (Clustered Index Seek && Table Scan)
и это быстро!Я могу вернуть более 100 000 записей за секунду, что соответствует нашим потребностям.
Однако, если у нас было больше UDF, и я изменил бы ограничение на что-то выше 66 (да, я проверялодин за другим) или, если я удаляю его полностью, я теряю сортировку в плане выполнения, и она заменяется целой кучей блоков параллелизма, которые собирают, перераспределяют и распределяют потоки, и все это происходит медленно (30 секунддаже для 1 записи).
FieldNumber имеет кластеризованный уникальный индекс и является частью составного первичного ключа со столбцом ID (некластеризованный индекс)в таблице ItemField .Столбцы ItemValue ID и ItemNumber таблицы образуют PK, и для столбца ItemNumber существует дополнительный некластеризованный индекс.
В чем причина этого?Почему изменение моего простого целочисленного ограничения меняет весь план выполнения?
И если вы готовы к этому ... что бы вы сделали по-другому? Планируется обновление SQLв течение пары месяцев, но мне нужно решить эту проблему до этого.