Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4   вперед  Ctrl      все
 Re: Передача табличной переменной в assembly процедуру  [new]
RubinDm
Member

Откуда:
Сообщений: 461
aleonov,

declare @T1 table (id int identity, val int, primary key (id));

insert into @T1 (val)
select  1 union all
select 23 union all
select  8 union all
select  9 union all
select  0;
select * from @T1 T1;

declare @T2 table (id int identity, val int, primary key (id));
insert into @T2 (val)
select 76 union all
select 11 union all
select  1 union all
select  2 union all
select  8;
select * from @T2 T2;

select top 1 AB.*
from 
( select -- все возможные пары из @T1
    a = A.val, b = B.val,
    pairLength = abs(B.id - A.id) -- расстояние между элементами пары
  from @T1 A
  join @T1 B on B.id >= A.id
) AB
join
( select -- все возможные пары из @T2
    x = X.val, y = Y.val,
    pairLength = abs(Y.id - X.id) -- расстояние между элементами пары
  from @T2 X join @T2 Y on Y.id >= X.id
) XY on AB.a = XY.x and AB.b = XY.y and AB.pairLength = XY.pairLength
order by AB.pairLength desc
go


declare @T1 table (id int identity, val int, primary key (id));

insert into @T1 (val)
select  1 union all
select 23 union all
select  8 union all
select  9 union all
select  0;
select * from @T1 T1;

declare @T2 table (id int identity, val int, primary key (id));
insert into @T2 (val)
select 76 union all
select 11 union all
select  8 union all
select  2 union all
select  1;
select * from @T2 T2;

select top 1 AB.*
from 
( select -- все возможные пары из @T1
    a = A.val, b = B.val,
    pairLength = B.id - A.id -- расстояние между элементами пары
  from @T1 A
  join @T1 B on B.id >= A.id
) AB
join
( select -- все возможные пары из @T2
    x = X.val, y = Y.val,
    pairLength = Y.id - X.id -- расстояние между элементами пары
  from @T2 X join @T2 Y on Y.id >= X.id
) XY on AB.a = XY.x and AB.b = XY.y and AB.pairLength = XY.pairLength
order by AB.pairLength desc
go


Очевидно, что есть огромное поле для оптимизаций. Например, надо работать только с теми значениями, которые встречаются в одновременно в обоих наборах данных. Мне самому стало интересно проверить и довести до ума решение на боевых данных. Если вас не затруднит - не могли бы вы каким угодно способом скинуть мне на medmedenok@yabdex.ru снимки реальных данных в реальных объемах, например, в формате xml (?).
18 май 12, 21:46    [12580461]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
aleonov
Из первого не следует второе, это может означать например, что других (кроме XML) способов нет.
Всё правильно, если бы не это: 12577327

aleonov
Затем что обработка строк и работа с памятью в CLR на порядок быстрее.
О боже, столько логически ошибок разом. Тяжело будет искоренять.
1. Строки самое что ни на есть тормоз к любому другому типу. Это ещё повезло есть колейшины в обоих систем совпадают.
2. Допустим в CLR строки работают быстрее чем в SQL (это не так, там просто больше функционал), но из этого не следует что нужно в них преобразовывать. Структурированные типы быстрее строковых (тупо нет преобразований) независимо от системы.
3. XML это не строка это сложная структура.
4. В контексте чётно видно: таблица -> генерация XML -> XML (передача) -> парсирование -> структура. Задлянафига?
Минимум: Таблица -> (передача) -> структура
Лучше: Таблица -> (нет передачи через параметры) -> Затягивание данный из контекста соединения
Ещё лучше: Разбор откуда взялист данные на сервере и сделать нужные подсчёты заранее, или до попадания на сервер или по мере попадания. Тут можно книгу написать про эффективность в целом, про равномерность нагрузки, про то что данные не крутятся по 100500 инстанциям, излишне преобразуясь в промежуточные формы.

aleonov
Можно вместо движения данных системы я опишу задачу номер 1 ?
Нет, не вместо, а вместе. Как буд-то можно заставить?!
Вы сами понимаете что правильно, а что нет. Лучше же быть честным с самим собой.

aleonov
Это задача широко известна для сравнения текстов как long common sequence. Мне же нужно, аналогичным образом сравнить данные в таблицах. Если решать в лоб без привлечения clr
Капец. Мне кажется вы не понимаете, вы веруете. Вы верите что великое императивное программирование всегда быстрее чем "тормознутое" декларативное, и небось что сиквел интерпретатор (не?). Но не понимая почему конкретно оно уступает или неудобно или лучше.
Иначе вы бы этого не написали.

Вот вы знали что в основном тупой вызов пустой скалярной функции медленее и дороже, чем даже криворуко написанному сложному выражению прямо в запросе?
Вы понимаете что проблема не в каких-то там мифических (т.к. плохо понимаете внутреннюю работу) аля запросах, а как эффективно просто поднять эти данные без лишних преобразований и передвижений. А в остальном работает нативный сверх-заточенный машинный код, главное понаписать поменьше глупостей.

Повторюсь, дело не в том что вы на сверх-заточенной CLRке добьётесь 10% профита, а на преобразовании и передаче потеряете 500%.
Дело в том что вы можете гордо тешить себя CLR и при этом выиграть 1200% на правильно организованной архитектуре потоков данных.
А в добавок, не откладывать понимание построение запросов на будующее, а сделать это обучение сейчас. Сравнить оба подхода и перестать верить.

Надеюсь, что всё не так плохо, как я представил.
-----------------------------------------------------------------------------------------------------------------------------------------------------
aleonov
Найти: наибольшую общую подпоследовательность данных в T1 и Т2
T1T2
176
2311
81
92
08
Общая подпоследовательность 1, 8
T1T2
176
2311
88
92
01
Общая подпоследовательность 8
-- Имеем индексы по [Value]

; WITH [Sequence] AS (
	SELECT	 X.[Value]
		,Row_Number()OVER(ORDER BY X.[Value])	AS [Number]
		,[Equal]
	FROM	          dbo.Tab1 T1
		FULL JOIN dbo.Tab2 T2 ON T2.[Value] = T1.[Value]	-- Merge
		CROSS APPLY (SELECT
			 IsNull(T1.[Value],T2.[Value])
			,CASE	WHEN T2.[Value] = T1.[Value]
				THEN Convert(Bit,1) ELSE Convert(Bit,0) END
		) X ([Value],[Equal])
)	SELECT	 Top(1) WITH TIES [Value]
	--	,[Number] - Row_Number()OVER(ORDER BY [Value])	AS [Group]
	FROM	[Sequence]
	WHERE	[Equal] = 1
	ORDER BY Count(*)OVER(PARTITION BY [Number] - Row_Number()OVER(ORDER BY [Value]))
	--	,[Number] - Row_Number()OVER(ORDER BY [Value])
-- Можно обвернуть в ещё один подзапрос, если чё
У кого там сервер под рукой - проверяйте.
Если ничего не перепутал и после исправления очепяток, увидите как ваши CLR и преобразования в XML будут нервно курить в сторонке.
-----------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос о передаче таблицы остаётся в силе. Надо все вопросы решать.
19 май 12, 03:17    [12581220]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Mnior
aleonov
Из первого не следует второе, это может означать например, что других (кроме XML) способов нет.
Всё правильно, если бы не это: 12577327
Ссори профтыкал это: 12577861
Но я уже приводил другой аргумент: дрогой способ - context connection. Затягивание данных, вместо впихивания.
19 май 12, 03:29    [12581223]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Кажись я выше решил другую задачу. Ссори.
Не это не беда. Будет ещё проще:
-- Имеем индексы по [ID]
-- Считаем что [ID] идёт строго подряд, без пропусков, иначе используем подзапросы:
-- (SELECT Row_Number()OVER(ORDER BY ID) AS ID, [Value] FROM dbo.Tab1) AS T1 ...

SELECT	 Top(1) WITH TIES [Value]
--	,T1.ID - T2.ID	AS Offset
FROM	     dbo.Tab1 T1
	JOIN dbo.Tab2 T2 ON T2.[Value] = T1.[Value]	-- Merge
ORDER BY Count(*)OVER(PARTITION BY T1.ID - T2.ID) DESC
--	,T1.ID - T2.ID
Вот DESC ещё проффтыкал в прошлый раз.
Даже не думайте о CLR.
19 май 12, 04:04    [12581231]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Уточню важную деталь оптимизации.
Максимально эффективно будет если ID идут строго подряд без дырок (подзапросы не нужны), и есть индекс по [Value]. Сработает Merge и сортировка будет иметь место один раз в плане, но точнее физически будет по другому - Sequence будет жрать больше всего.
Если я не путаю, то сложность примерно: 2N + N*Log(N)
19 май 12, 04:29    [12581239]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
aleonov
Member

Откуда:
Сообщений: 96
RubinDm
Очевидно, что есть огромное поле для оптимизаций. Например, надо работать только с теми значениями, которые встречаются в одновременно в обоих наборах данных. Мне самому стало интересно проверить и довести до ума решение на боевых данных. Если вас не затруднит - не могли бы вы каким угодно способом скинуть мне на medmedenok@yabdex.ru снимки реальных данных в реальных объемах, например, в формате xml (?).


Задачка действительно интересная, но когда вникните глубже то поймете что с наскоку не решается. "Боевые" данные на рабочем сервере, могу скинуть в понедельник, но более впечатляющие результаты получаются на сгенерированных данных.
19 май 12, 20:38    [12582543]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
aleonov
Member

Откуда:
Сообщений: 96
Mnior
1. Строки самое что ни на есть тормоз к любому другому типу. Это ещё повезло есть колейшины в обоих систем совпадают.


Что конкретно имеется ввиду ?

Mnior
2. Допустим в CLR строки работают быстрее чем в SQL (это не так, там просто больше функционал), но из этого не следует что нужно в них преобразовывать. Структурированные типы быстрее строковых (тупо нет преобразований) независимо от системы.


На самом деле в CLR строки работают быстрее чем в SQL .

Пример.
Строка '1,2,3,4,5,6,7,8,9,10,11,12...' разделитель запятая, разложите строку на составляющие. По-моим наблюдениям любой Ваш код будет минимум в два раза медленее чем метод Split().

Во-вторых, преобразования есть практически всегда, при вызове кода и выводе данных, сравнениях проверках и т.п.

Пример.

select * from table where date = '?'; -< параметр строка, которая неявно преобразуется в тип дата/время. ну и практически в 90% случаев происходит преобразование типов, когда вызывается хранимая процедура/функция

Mnior
3. XML это не строка это сложная структура.


Да, когда объявлен явно xml тип и его структура, в остальных случаях просто длинная строка.

Mnior
4. В контексте чётно видно: таблица -> генерация XML -> XML (передача) -> парсирование -> структура. Задлянафига?
Минимум: Таблица -> (передача) -> структура
Лучше: Таблица -> (нет передачи через параметры) -> Затягивание данный из контекста соединения
Ещё лучше: Разбор откуда взялист данные на сервере и сделать нужные подсчёты заранее, или до попадания на сервер или по мере попадания. Тут можно книгу написать про эффективность в целом, про равномерность нагрузки, про то что данные не крутятся по 100500 инстанциям, излишне преобразуясь в промежуточные формы.


Абсолютно верно, но специфика такова что нужно обрабатывать данные уже сохранненые на сервере и не по мере поступления, а целиком.

Mnior
Капец. Мне кажется вы не понимаете, вы веруете. Вы верите что великое императивное программирование всегда быстрее чем "тормознутое" декларативное, и небось что сиквел интерпретатор (не?). Но не понимая почему конкретно оно уступает или неудобно или лучше.
Иначе вы бы этого не написали.

Вот вы знали что в основном тупой вызов пустой скалярной функции медленее и дороже, чем даже криворуко написанному сложному выражению прямо в запросе?
Вы понимаете что проблема не в каких-то там мифических (т.к. плохо понимаете внутреннюю работу) аля запросах, а как эффективно просто поднять эти данные без лишних преобразований и передвижений. А в остальном работает нативный сверх-заточенный машинный код, главное понаписать поменьше глупостей.

Повторюсь, дело не в том что вы на сверх-заточенной CLRке добьётесь 10% профита, а на преобразовании и передаче потеряете 500%.
Дело в том что вы можете гордо тешить себя CLR и при этом выиграть 1200% на правильно организованной архитектуре потоков данных.
А в добавок, не откладывать понимание построение запросов на будующее, а сделать это обучение сейчас. Сравнить оба подхода и перестать верить.

Надеюсь, что всё не так плохо, как я представил.


Нет не все так плохо, я отчетливо себе представляю почему SQL движок тормозит на такой задаче и проблема вовсе не в преобразованиях, которые от всей логики занимают <1%. Проблема в специфике задачи, которая на двух таблицах по 10 тыс. записей требует обновления примерно 10 млн. записей.



Mnior

-- Имеем индексы по [Value]

; WITH [Sequence] AS (
SELECT X.[Value]
,Row_Number()OVER(ORDER BY X.[Value]) AS [Number]
,[Equal]
FROM dbo.Tab1 T1
FULL JOIN dbo.Tab2 T2 ON T2.[Value] = T1.[Value] -- Merge
CROSS APPLY (SELECT
IsNull(T1.[Value],T2.[Value])
,CASE WHEN T2.[Value] = T1.[Value]
THEN Convert(Bit,1) ELSE Convert(Bit,0) END
) X ([Value],[Equal])
) SELECT Top(1) WITH TIES [Value]
-- ,[Number] - Row_Number()OVER(ORDER BY [Value]) AS [Group]
FROM [Sequence]
WHERE [Equal] = 1
ORDER BY Count(*)OVER(PARTITION BY [Number] - Row_Number()OVER(ORDER BY [Value]))
-- ,[Number] - Row_Number()OVER(ORDER BY [Value])
-- Можно обвернуть в ещё один подзапрос, если чё

[/src]У кого там сервер под рукой - проверяйте.
Если ничего не перепутал и после исправления очепяток, увидите как ваши CLR и преобразования в XML будут нервно курить в сторонке.
-----------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос о передаче таблицы остаётся в силе. Надо все вопросы решать.


конечно курят, только результат скорее всего неверный
19 май 12, 21:32    [12582718]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
aleonov
Mnior
Это ещё повезло есть колейшины в обоих систем совпадают.
Что конкретно имеется ввиду ?
Помучаю, не скажу сразу. Интересна реакция.
aleonov
Mnior
2. Допустим в CLR строки работают быстрее чем в SQL (это не так, там просто больше функционал), но из этого не следует что нужно в них преобразовывать.
любой Ваш код будет минимум в два раза медленее чем метод Split().
Просто выделил поярче. SubString одинаков по скорости плюс минус один попугай. Те же самые команды.
aleonov
преобразования есть практически всегда, при вызове кода и выводе данных, сравнениях проверках и т.п.
Умора.
- Лучше делать меньше преобразований!
- Нет. Они есть всегда.

aleonov
select * from table where date = '?'; -- параметр строка, которая неявно преобразуется в тип дата/время. ну и практически в 90% случаев происходит преобразование типов, когда вызывается хранимая процедура/функция
Кто ж спорит то, в говнокоде дофига лишних преобразований. Из примеров видно что злоупотребляете. И это аргумент?

Вы не сможете доказать что Convert(VarChar,@Str,104) будет тормозом, чем аналог на CLR.
aleonov
Mnior
3. XML это не строка это сложная структура.
Да, когда объявлен явно xml тип и его структура, в остальных случаях просто длинная строка.
- Когда переменная типа XML, то переменная типа XML, а когда переменная типа строка, то переменная типа строка.

А сколько этих остальных случаев?
Мда, недопонимание довольно тотальное. Стало очевидным, почему у вас заело про "обрезание" данных, только все остальные как-то не решились писать.
Но самое прикольное, что как-то продолжает подозреваться, что поиск подпоследовательности чисел будет вестись в строках.
aleonov
но специфика такова что нужно обрабатывать данные уже сохранненые на сервере и не по мере поступления, а целиком.
- Вот тачка, клиент сказал, что хочет чтоб она ехала быстрее.
- <что-то делает>
- Ты что делаешь?! Нафига ты сзади комбайн прикручиваешь. Ты должен тупо снять старый движёк и поставить новый.
Можно было и не писать эти ничего не значащие 18 слов или можно проще - "Так нада".
aleonov
Нет не все так плохо, я отчетливо себе представляю почему SQL движок тормозит на такой задаче
А мне кажется всё очень плачевным и ... грустным.
Ну, поделитесь с нами секретом почему конкретно SQL так убог, что и рядом не стоит с великим и ужасным в решении данной задачи.
aleonov
проблема вовсе не в преобразованиях, которые от всей логики занимают <1%.
Ну да, конечно. Ну покажите это нам.
Создайте функцию, в которой тупо 2 XML в массивы запихнёте. Потом скрипт на генерацию XMLей из таблиц и вызов этой функции.
aleonov
Проблема в специфике задачи, которая на двух таблицах по 10 тыс. записей требует обновления примерно 10 млн. записей.

Обновления???
Миллионов???
Если в этой CLR для поиска подпоследовательностей надо 10 мил. операций. То нужно мне в скрипте WAITFOR добавить, так для "выравнивания шансов".
aleonov
конечно курят, только результат скорее всего неверный
Что-то не видно ответа на последний пост 12581231.

Ладно, слишком уж позлорадствовал.
----------------------------------------------------------------------------------------------------------------
Советую тебе поступать на ФизТех. Когда "выдающийся гений" местного разлива попадает в среду минимум таких же. Вся спесь и тотальная непоколебимость в себе любимом оказывается нехилым камнем на сердце. Некоторые ломаются.

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

Совсем не достаточно увидеть знакомые слова и выложить свои знания по ним. Нужно проверить на применимость этих знаний, даёт ли данная модель все побочные эффекты, все ли детали сходятся. И это не всё. Нужно далее по найденым несостыковкам подобрать такую модель (выкидывая/изменяя/добавляя аксиомы и предположения) при которой они сойдутся (но не сойдутся другие). Нарабатывать статистику, какие "аксиомы" чаще "упускают". Ставить под сомнения и находить примеры когда модели приходят к разным результатом, поставить опыт для разрешения конфликта.
Ой что-то меня развезло.

Кароче, некоторые видят в этом сложности и боятся как огня, а некоторые живут этим.

aleonov, как вы думаете, боюсь ли я оказаться "неправым"?
А "ошибиться в рассуждениях"?
20 май 12, 00:19    [12583459]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
aleonov
Пример.
Строка '1,2,3,4,5,6,7,8,9,10,11,12...' разделитель запятая, разложите строку на составляющие. По-моим наблюдениям любой Ваш код будет минимум в два раза медленее чем метод Split().

Ну давайте чтоль потестируем. Пишите свою CLR и поглядим.
20 май 12, 00:43    [12583550]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
aleonov
Member

Откуда:
Сообщений: 96
Mnior
Ой что-то меня развезло.


eсли разве(з)ло, то лучше не пиши на серьезные темы :-) одна "вода" и ни одной дельной мысли. могу тебе на мыло сбросить данные из таблиц с ответом, можешь сам себя проверить. если твое решение будет выполняться секунд хотя бы за 15 и сделаешь не позже чем за неделю с меня бутылка коньяка.
20 май 12, 00:45    [12583561]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
aleonov
Mnior
Ой что-то меня развезло.


eсли разве(з)ло, то лучше не пиши на серьезные темы :-) одна "вода" и ни одной дельной мысли. могу тебе на мыло сбросить данные из таблиц с ответом, можешь сам себя проверить. если твое решение будет выполняться секунд хотя бы за 15 и сделаешь не позже чем за неделю с меня бутылка коньяка.

Ну так что на счет очередного тестирования CLR? А то ведь где-то раз в полгода/год обязательно появляется очередной фанатик и начинаем в очередной раз тестировать))). Цифры вас удивят, гарантирую. Особенно на больших наборах данных.
20 май 12, 00:48    [12583580]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
aleonov
Member

Откуда:
Сообщений: 96
kDnZP
aleonov
Пример.
Строка '1,2,3,4,5,6,7,8,9,10,11,12...' разделитель запятая, разложите строку на составляющие. По-моим наблюдениям любой Ваш код будет минимум в два раза медленее чем метод Split().

Ну давайте чтоль потестируем. Пишите свою CLR и поглядим.


using System.Collections;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public static class TP
{

// Text Parser
[SqlFunction(FillRowMethodName = "TPFillRow",
TableDefinition = "id int, line nvarchar(max)")]
public static IEnumerator CLR_TP(SqlString txt, SqlString delimeter)
{
return new TextParser(txt, delimeter);
}

// Fill in output record set for CLR_TP
private static void TPFillRow(object row, out SqlInt32 id, out SqlString line)
{

TextParser s = (TextParser)row;
id = s.current_index + 1;
line = s.current_line;
}

}
// Class to parse text into list
public class TextParser : IEnumerator
{
public int current_index;
public string current_line;

private int index = -1;
private int size = -1;
private string[] lines;
private char[] chars;

public TextParser(SqlString txt, SqlString delimeter)
{

if (delimeter.ToString() == "" || delimeter.IsNull)
{
chars = txt.Value.ToCharArray();
lines = new string[chars.Length];
for (int i = 0, max = chars.Length; i < max; i++)
lines[i] = chars[i].ToString();

}
else
{
lines = txt.Value.Split(delimeter.ToString().ToCharArray());
}

size = lines.Length;

}
public bool MoveNext()
{
if (index == size - 1)
return false;

current_index = ++index;
current_line = lines[index];

return true;
}
public bool MovePrior()
{
if (index == -1)
return false;

current_index = --index;
current_line = lines[index];

return true;
}
public object Current
{
get
{
if (index != -1)
return this;
else
return null;
}
}
public void Reset()
{
index = -1;
}
public void Reset(short type)
{
if (type == 0)
index = -1;
else
index = size;
}


}



Собери в TP.dll, затем в скуле
create assembly tp from 'd:\tp.dll'
go

/****** Object: UserDefinedFunction [dbo].[fn_parse] Script Date: 05/19/2012 22:16:08 ******/
CREATE FUNCTION [dbo].[fn_tp](@string [nvarchar](max), @delimeter [nvarchar](max))
RETURNS TABLE (
[id] [int] NULL,
[line] [nvarchar](max) NULL
) WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [TP].[TP].[CLR_TP]
GO

select * from fn_tp('1,2,3,4,5,6,7,8,9',',')


Протестируй на длинных строках длиной 10к и выше
20 май 12, 01:21    [12583686]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
aleonov
Member

Откуда:
Сообщений: 96
[quot kDnZP]
aleonov
пропущено...


Цифры вас удивят, гарантирую. Особенно на больших наборах данных.


я жду... очень хочу удивиться.. :-)
20 май 12, 01:23    [12583700]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Deff
Member

Откуда: Пермь
Сообщений: 18328
Mnior
Ладно, слишком уж позлорадствовал.
Слишком. Можно сказать "не формат" для данного форума.
20 май 12, 02:03    [12583791]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
aleonov
+
using System.Collections;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public static class TP
{

    // Text Parser 
    [SqlFunction(FillRowMethodName = "TPFillRow",
                 TableDefinition = "id int, line nvarchar(max)")]
    public static IEnumerator CLR_TP(SqlString txt, SqlString delimeter)
    {
        return new TextParser(txt, delimeter);
    }

    // Fill in output record set for CLR_TP
    private static void TPFillRow(object row, out SqlInt32 id, out SqlString line)
    {

        TextParser s = (TextParser)row;
        id = s.current_index + 1;
        line = s.current_line;
    }

}
////////////////////////
// Совершенно бесполезный троллинговый кусок текста, занимающий большую часть
////////////////////////
// Class to parse text into list
public class TextParser : IEnumerator
{
    public int current_index;
    public string current_line;

    private int index = -1;
    private int size = -1;
    private string[] lines;
    private char[] chars;

    public TextParser(SqlString txt, SqlString delimeter)
    {

        if (delimeter.ToString() == "" || delimeter.IsNull)
        {
            chars = txt.Value.ToCharArray();
            lines = new string[chars.Length];
            for (int i = 0, max = chars.Length; i < max; i++)
                lines[i] = chars[i].ToString();

        }
        else
        {
            lines = txt.Value.Split(delimeter.ToString().ToCharArray());
        }

        size = lines.Length;

    }
    public bool MoveNext()
    {
        if (index == size - 1)
            return false;

        current_index = ++index;
        current_line = lines[index];

        return true;
    }
    public bool MovePrior()
    {
        if (index == -1)
            return false;

        current_index = --index;
        current_line = lines[index];

        return true;
    }
    public object Current
    {
        get
        {
            if (index != -1)
                return this;
            else
                return null;
        }
    }
    public void Reset()
    {
        index = -1;
    }
    public void Reset(short type)
    {
        if (type == 0)
            index = -1;
        else
            index = size;
    }

  
}
Собери в TP.dll, затем в скуле
create assembly tp from 'd:\tp.dll'
go
CREATE FUNCTION [dbo].[fn_tp](@string [nvarchar](max), @delimeter [nvarchar](max))
RETURNS  TABLE (
	[id] [int] NULL,
	[line] [nvarchar](max) NULL
) WITH EXECUTE AS CALLER AS EXTERNAL NAME [TP].[TP].[CLR_TP]
GO
select * from fn_tp('1,2,3,4,5,6,7,8,9',',')
Протестируй на длинных строках длиной 10к и выше
Немного для смягчения глаз.
Прикольнуло nvarchar(max) и целый бесполезный класс, занимающий больше всего.

Теперь нужен код для генерации:
DECLARE	@Array	VarChar(max)
SELECT	@Array = Stuff((
SELECT	',',A.number AS [*]
FROM	master.dbo.spt_values A, master.dbo.spt_values B, master.dbo.spt_values C
WHERE	type ='P' -- AND number < 10
FOR XML Path(''),Type).value('text()[1]','VarChar(max)'),1,1,'') -- Быстрее не бывает
Потом надо ещё дописать в эту DLL функцию, которая читает запрос напрямую из контекста.
	[SqlFunction(
		 DataAccess = DataAccessKind.Read,
		 FillRowMethodName = "fnTest_FillRow",
		 TableDefinition="Value int")]
	public static IEnumerable fnTest(SqlString query) {
		ArrayList result = new ArrayList(); // тут нужно ещё запилить

		using (SqlConnection connection = new SqlConnection("context connection=true")) {
			connection.Open();

			using (SqlCommand select = new SqlCommand(query.Value, connection))
			using (SqlDataReader reader = select.ExecuteReader())
				while (reader.Read()) 
					result.Add(reader.GetSqlInt32(0));
		}
		return result;
	}

	public static void fnTest_FillRow(object ResultObj, out SqlInt32 Value) {
		Value = (SqlInt32)ResultObj;
	}
А потом сравнить, сколько занимают преобразования в строку и обратно (хотя там же nvarchar(max), а не Int) и без преобразований. Только всё это тщетно, не получится через SqlString передать строку более 4K символов. Тут нужен SqlChars.

Надо ещё inline функцию на нативном SQL (можно допилить это 8147002). Чтоб потешил себя TC в заблуждении, что проблема мол в тормозной работе скуля со строками, а не в том что банально нет функционала (того же Split) или ещё в чём-то. Потом надо сделать функцию SubString на CLR. Чтоб чел увидел своими глазами как дорого тупо вызвать что-то из CLR (хотя для одноразового это не важно).

Ну а потом вернёмся к суровой реальности: 12581231
20 май 12, 04:36    [12583859]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
aleonov
я жду... очень хочу удивиться.. :-)

Ну чтож... Вынужден признать, что именно реализация этой функции (т.е. разбор строки в таблицу) не настолько тормознутая, как другие CLR. Более того, даже дает копеечный выигрыш:

Единственно, что при тестирововании с действительно большими строками получал:

Сообщение 6532, уровень 16, состояние 49, строка 61
.NET Framework execution was aborted by escalation policy because of out of memory.
System.Threading.ThreadAbortException: Поток находился в процессе прерывания.
System.Threading.ThreadAbortException:
в System.String.Split(Char[] separator, Int32 count, StringSplitOptions options)
в TextParser..ctor(SqlString txt, SqlString delimeter)
в TP.CLR_TP(SqlString txt, SqlString delimeter)
The statement has been terminated.

но это уже мелочи)))

+ Результаты:


SQL Server Execution Times:
CPU time = 10936 ms, elapsed time = 11513 ms.

(строк обработано: 1024000)

SQL Server Execution Times:
CPU time = 12527 ms, elapsed time = 13076 ms.

Microsoft SQL Server 2008 (SP2) - 10.0.4000.0 (Intel X86)
Sep 16 2010 20:09:22
Copyright (c) 1988-2008 Microsoft Corporation
Express Edition on Windows NT 6.1 <X86> (Build 7601: Service Pack 1)

Время работы SQL Server:
Время ЦП = 11919 мс, затраченное время = 12507 мс.

(строк обработано: 1024000)

Время работы SQL Server:
Время ЦП = 12511 мс, затраченное время = 12876 мс.

(строк обработано: 1024000)

Microsoft SQL Server 2008 R2 (SP1) - 10.50.2500.0 (Intel X86)
Jun 17 2011 00:57:23
Copyright (c) Microsoft Corporation
Developer Edition on Windows NT 6.1 <X86> (Build 7601: Service Pack 1)


+ Скрипт тестирования:
/*
EXEC sp_configure 'show advanced options' , '1';
go
reconfigure;
go
EXEC sp_configure 'clr enabled' , '1'
go
reconfigure;
EXEC sp_configure 'show advanced options' , '1';
go
*/

/*
create assembly tp from 'd:\2\tp.dll'
go

--****** Object: UserDefinedFunction [dbo].[fn_parse] Script Date: 05/19/2012 22:16:08 ******
CREATE FUNCTION [dbo].[fn_tp](@string [nvarchar](max), @delimeter [nvarchar](max))
RETURNS TABLE (
[id] [int] NULL,
[line] [nvarchar](max) NULL
) WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [TP].[TP].[CLR_TP]
GO
*/

DECLARE @tst1 NVARCHAR(MAX)
DECLARE @tst2 XML
DECLARE @limit INT=500 -- <2048

SELECT	@tst1=Stuff((
SELECT  ','+LTRIM(STR(v1.number + v2.number * 2048))
FROM    master..spt_values v1
        INNER JOIN master..spt_values v2 ON v2.number < @limit
                                            AND v2.type = 'P'
WHERE   v1.type = 'P'
FOR XML Path(''),Type).value('text()[1]','VarChar(max)'),1,1,'') -- Быстрее не бывает
, @tst2=(
SELECT  CAST(v1.number + v2.number * 2048 AS NVARCHAR(MAX)) c
FROM    master..spt_values v1
        INNER JOIN master..spt_values v2 ON v2.number < @limit
                                            AND v2.type = 'P'
WHERE   v1.type = 'P'
FOR XML Path('')
)

SET STATISTICS TIME ON
SELECT  *
INTO #tst1
FROM    fn_tp(@tst1,',') t1
SET STATISTICS TIME OFF

SET STATISTICS TIME ON
select x.y.value('.', 'varchar(max)')res, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) rn
INTO #tst2
from @tst2.nodes('/c') x(y)
SET STATISTICS TIME OFF

SELECT TOP 10 * FROM #tst1 ORDER BY id
SELECT TOP 10 * FROM #tst2 ORDER BY rn

DROP TABLE #tst1
DROP TABLE #tst2

SELECT @@VERSION



Но даже признавая, что я неправ, в то же время
aleonov
Пример.
Строка '1,2,3,4,5,6,7,8,9,10,11,12...' разделитель запятая, разложите строку на составляющие. По-моим наблюдениям любой Ваш код будет минимум в два раза медленее чем метод Split().

тоже не есть верным утверждением.
20 май 12, 11:28    [12584025]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
aleonov
Member

Откуда:
Сообщений: 96
Mnior
А потом сравнить, сколько занимают преобразования в строку и обратно (хотя там же nvarchar(max), а не Int) и без преобразований. Только всё это тщетно, не получится через SqlString передать строку более 4K символов. Тут нужен SqlChars.

Надо ещё inline функцию на нативном SQL (можно допилить это 8147002). Чтоб потешил себя TC в заблуждении, что проблема мол в тормозной работе скуля со строками, а не в том что банально нет функционала (того же Split) или ещё в чём-то. Потом надо сделать функцию SubString на CLR. Чтоб чел увидел своими глазами как дорого тупо вызвать что-то из CLR (хотя для одноразового это не важно).

Ну а потом вернёмся к суровой реальности: 12581231


Не пишите глупостей, что ни предложение, то казус.
Суровая реальность такова, что задачу номер 1 вы так и не решили, задачу номер 2 - пропарсить строку функциями SQL тоже. Вместо этого придумали свою задачу - написать аналог SubString на CLR. :-) Вот там ниже пост, в котором действительно профи, признает что да CLR на задаче 2 быстрее.
20 май 12, 12:37    [12584149]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
aleonov
Member

Откуда:
Сообщений: 96
kDnZP
aleonov
я жду... очень хочу удивиться.. :-)

Ну чтож... Вынужден признать, что именно реализация этой функции (т.е. разбор строки в таблицу) не настолько тормознутая, как другие CLR. Более того, даже дает копеечный выигрыш:

Единственно, что при тестирововании с действительно большими строками получал:

Сообщение 6532, уровень 16, состояние 49, строка 61
.NET Framework execution was aborted by escalation policy because of out of memory.
System.Threading.ThreadAbortException: Поток находился в процессе прерывания.
System.Threading.ThreadAbortException:
в System.String.Split(Char[] separator, Int32 count, StringSplitOptions options)
в TextParser..ctor(SqlString txt, SqlString delimeter)
в TP.CLR_TP(SqlString txt, SqlString delimeter)
The statement has been terminated.

но это уже мелочи)))


Но даже признавая, что я неправ, в то же время
aleonov
Пример.
Строка '1,2,3,4,5,6,7,8,9,10,11,12...' разделитель запятая, разложите строку на составляющие. По-моим наблюдениям любой Ваш код будет минимум в два раза медленее чем метод Split().

тоже не есть верным утверждением.


Браво! Только речь шла об использовании встроенных функциях SQL как-то substring и т.п. Mnior доказывал что решение с использованием substring будет ничуть не хуже.

Я например, сравнивал вот с такой /****** Object: UserDefinedFunction [dbo].[fn_getrsetfromstr] Script Date: 05/20/2012 09:38:05 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[fn_getrsetfromstr] (@string varchar(max), @delimiter char(1))
/*
Description: Returns result set of paired values
(id, description) from a string of values
delimited by a character
=============================================

Parameters:

@string varchar(max) - String of values delimited by a character
@delimiter char(1) - Delimiter

Examples:

Return values from a string delimited by '|' character
select * from fn_getrsetfromstr( 'Test1|Test2', '|' )

=============================================
*/
RETURNS @resultset table ( id int identity(1,1), description varchar(1000) )
as
begin


declare @current_position int
declare @last_position int
declare @description varchar(1000)

if @string is null or @delimiter is null
return

set @last_position = 1
set @current_position = charindex(@delimiter,@string, @last_position)

while @current_position <> 0
begin

set @description = substring(@string,@last_position,@current_position - @last_position )

insert into @resultset ( description ) values ( @description )

set @last_position = @current_position + 1
set @current_position = charindex(@delimiter,@string, @last_position)

end

if @current_position = 0
begin
set @description = substring(@string,@last_position,1000 )
insert into @resultset ( description ) values ( @description )
end

return

end

На вашем тесте эта функия в 3 раза медленнее.
20 май 12, 12:45    [12584172]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
kDnZP
+ тест
SET STATISTICS TIME ON
SELECT  *
INTO #tst1
FROM    fn_tp(@tst1,',') t1
SET STATISTICS TIME OFF

SET STATISTICS TIME ON
select x.y.value('.', 'varchar(max)')res, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) rn
INTO #tst2
from @tst2.nodes('/c') x(y)
SET STATISTICS TIME OFF
Панимаете, kDnZP, вы пытаетесь вести себя благородно перед этим ... "воином", который совершенно не может выразить свои мысли, и готов за цифры в вакууме совершенно другой задачи считать что он прав во всём (важно не понимание же, важна же "победа") (ну как мне видится на данный момент).
Но на самом деле делаете хуже всей ситуации, делая ошибки, "подняв лапки". Совершенно непонятно, о чём вы с ним "спорили".

1. Вы сравнили пол его задачи, которая заключается в "генерированию строки + парсировании", и замеряли половину кода.
Его утверждение было лишь в том, что "генерация + парсирование" займёт <1% по сравнению с прямой передачей. Перевираю?
2. С другой стороны, вы подаёте XML. Но это "мошенничество" к его утверждениям - у него строка, так и к моим, ибо работа с XML работает тоже не нативно, а через вызов (того же CLR). Сравнивая тёплое с мягким.
3. Он утверждал не то что скуль "тормоз", а то что строки обрабатываются медленее. Т.е. SubString/Stuff/CharIndex ... в скуле работает медленнее чем SubString/Stuff/CharIndex ... в CLR.
4. Проблема в том, что он не писал и не пишет почему что да как. Ибо он не знает.
Вот что он пишет:
aleonov
Затем что обработка строк и работа с памятью в CLR на порядок быстрее.

1. На порядок быстрее. Ок. Здесь он получил полный облом. Но не на это я концентрировался. Это не важно на сколько. И пример ничего не показывает.
2. обработка строк и работа с памятью - вот!, проблема в непонимании (или неточности) - строки и память тут совершенно не причём. Функции из обоих сред вызываются те же самые. Функционал у скуля намного ниже. Был бы Split (и другие функции) на скуле он бы не утверждал вышесказанное.

Вот смотрите. Он продолжает, читая по диагонали, перевирая мои слова:
aleonov
Mnior доказывал что решение с использованием substring будет ничуть не хуже.
Естественно. Он ведь реагирует на наборы слов, вырывая их контекста, а не на смысловые предложения. Ну я уже писал почему.
И приводит что?, правильно, императивщину на декларативном языке:
aleonov
+ fn_getrsetfromstr
ALTER function [dbo].[fn_getrsetfromstr] (@string varchar(max), @delimiter char(1))
RETURNS @resultset table ( id int identity(1,1), description varchar(1000) ) 
 as 
begin


declare @current_position int
declare @last_position int
declare @description varchar(1000)

if @string is null or @delimiter is null 
	return 

set @last_position = 1
set @current_position = charindex(@delimiter,@string, @last_position)

while  @current_position <> 0 
   begin

	set @description = substring(@string,@last_position,@current_position - @last_position  )

	insert into @resultset ( description ) 	values (  @description ) 

	set @last_position = @current_position + 1
	set @current_position = charindex(@delimiter,@string, @last_position)
	
   end

if @current_position = 0
 begin
  set @description = substring(@string,@last_position,1000  )
  insert into @resultset ( description ) 	values (  @description ) 
end 

return 

end
Хотя я ранее привёл нормальный скрипт 8147002. Ах нуда, он же читает посты по диагонали, упуская детали.
А почему:
1. Императивист? Хотя это было с самого начало очень сверх вероятно. Тут уже 100500 ответов.
2. Приводит один из "источников" его "уверенности". Аллилуйя. Из-за чего до него в итоге может дойти смысл первого же моего поста на его неточное описание проблемы. И возможно поймёт, что он совершенно неправильно интерпретировал слова и вообразил себе "поединок".
Но это вряд ли, чувство "победы любой ценой", чувство "не проиграть", чувство что "я всегда прав", чувство "я никогда не допускаю ошибки и неточности" намного сильнее чувства истины и точности. Или возможно совершает логическую ошибку что мол "если я признаюсь, то он 'победил' и все его утверждения в мою сторону станут весомыми". *лять, мои утверждения станут тогда не верными!

aleonov
Вместо этого придумали свою задачу - написать аналог SubString на CLR.
Аналогично. Он не хочет проверить и признать что тупо вызов внешней функции дорого и это существенно при использовании, и что это я показываю для него, для точного понимания что к чему. Что проблема "тормозов" не в строках или памяти. В чём именно, напишеться после. Если конечно ему будет интересно, что совершенно не видно.

aleonov
Не пишите глупостей, что ни предложение, то казус.
Правильно. Использование 4го правило троллей.
Если бы он был в ступоре от многа-букав, то просто пере-спросил. Можно было лично, что да как, объясниться, медленно и по кусочкам.
Но ему пофигу, т.к. он человек веры, он отмазался от всех деталей, упростив понимание мира, залез в танк - "собеседник глуп, вникать в смысл его слов и читать, слаба богу не надо".
И показывает неуважение к собеседнику и свой пофигизм на окружающих, тем что игнорирует их аргументы и утверждения (не важно на 90%, 30% или 0.01%).
Не написав хотя бы одну причину, в чём он (то есть я) ошибается, в чём конкретно ошибка в его (то есть моей) цепочке утверждений. Нет, типа лучше сконцентрироваться на кто "победит", за кем "последнее слово". Не?

------------------------------------------------------------------
Но что по сути задачи?
Пишется и не раз.
aleonov
Суровая реальность такова, что задачу номер 1 вы так и не решили
Игнорируя основной пост 12581231.
Ладно бы если я ошибся, с кем не бывает. Но тогда бы он просто показал, что вот мол запустил пример, вот результат, ошибка очевидно. Но нет - сухое "не решили". Ощущение, словно "прижал хвост". И боится копать в этом направлении, не дай бог решение.

&%@ть, aleonov, неужели понять суть и особенности работы скуля меркнут на фоне "победить" в придуманной вами "схватке"? Адреналин так замутил вам голову?


Фиг с ним, kDnZP, вы то что никак не реагируете по основной задаче.

В итоге уже 2 дня срача прошли, а завтра можно уже самому взять скуль и все проверить и показать.
Но хрен же с этой задачей, намного ценнее не решить её конкретно, а научиться решать их все вообще. И исправлять свои неточности в понимании происходящего.
------------------------------------------------------------------
PS: За любую интерпретацию моих слов как личное оскорбление, прошу заранее прощение.
Любые мои предположения (выдвинутые на основе произошедшего) могут быть не верны, но банально требуют контр аргументов.
Есть места провокационного типа, для привлечения внимания (на что стоит ответить/спросить) и для предотвращения возможных ошибок.
Оскорбить не хотел, в "переходе на личности" не вижу никакого смысла.
Любая аргументированная и хорошо обоснованная критика в мою сторону приветствуется.
21 май 12, 03:02    [12585915]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
aleonov, знаете что вы не учитываете, когда сравниваете с Longest common subsequence problem (LCSSP)?
Что данные уже заранее могут быть подготовлены специальным образом и обработаны. Наличие индекса об этом и говорит.

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

Я могу ускорить своё решение ещё намного, повесив банально ещё один индекс - на представление (если я учитываю все ограничения). Тогда выдаваться будет пулей. Но какой ценой. Хотя вы на это не сконцентрировались, а зря.
21 май 12, 03:26    [12585920]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
aleonov
Подскажите, возможно ли в assembly процедуру передать табличную переменную ? Если кто сталкивался с этим, киньте примерчик, спасибо.

Можно, как уже говорилось ранее через табличный тип:
http://msdn.microsoft.com/en-us/library/ms131103
http://msdn.microsoft.com/en-us/library/bb510489

Mnior
Панимаете, kDnZP, вы пытаетесь вести себя благородно перед этим ... "воином", который совершенно не может выразить свои мысли, и готов за цифры в вакууме совершенно другой задачи считать что он прав во всём (важно не понимание же, важна же "победа") (ну как мне видится на данный момент).
Но на самом деле делаете хуже всей ситуации, делая ошибки, "подняв лапки". Совершенно непонятно, о чём вы с ним "спорили".

Если я неправ, то я неправ. Не вижу ничего плохо в признании своих ошибок. Да это неприятно, да хотелось бы ошибаться пореже. Да, я все равно уверен, что CLR, курсоры, циклы по-большей части зло. Но. Для данного, конкретного случая - CLR оправдан и быстрее. Реализация split через xquery практически равнозначна по скорости, но по правде говоря всеж-таки тоже имеет ограничения (как впрочем и CLR: т.е. расход памяти под CLR, кардиналити = 1000 и т.д.). Но все эти оговорки не меняют того факта, что split на CLR весьма быстр и как следствие я это запомню .

Mnior
1. Вы сравнили пол его задачи, которая заключается в "генерированию строки + парсировании", и замеряли половину кода.

Я честно говоря вообще не врубился в то, об чем задача... Как следствие оперирую только с тем, что понимаю.
Mnior
2. С другой стороны, вы подаёте XML. Но это "мошенничество" к его утверждениям - у него строка, так и к моим, ибо работа с XML работает тоже не нативно, а через вызов (того же CLR). Сравнивая тёплое с мягким.
3. Он утверждал не то что скуль "тормоз", а то что строки обрабатываются медленее. Т.е. SubString/Stuff/CharIndex ... в скуле работает медленнее чем SubString/Stuff/CharIndex ... в CLR.

Я могу реализовать разбор через коррелированные подзапросы или рекурсию. Более того, я их реализовал. Показывать не стал, медленные они... Печально, но факт. И, кстати, вполне объяснимо почему они медленнее, нежели однопроходная разрезалка на CLR или циклах (кстати, с рекурсивной функцией вообще работать неудобно, т.к. надобно не забывать про снятие ограничение на глубину рекурсии, и делать это нужно снаружи).
Т.е. опять все та же самая ситуация. Признавать, что я не прав тяжко, но факт есть факт. и за реализацию SQL-функции резалки на циклах можно только похвалить ТС, если это было сделано осознанно, по сравнению с другими вариантами*.
* Дело в том что даже если вернуться к xquery, то при постановке задачи - резать именно строки разделенные запятыми - нужно реплейсить запятые для преведения к XML... А это жутко дорого(((.
Mnior
Игнорируя основной пост 12581231.
Ладно бы если я ошибся, с кем не бывает. Но тогда бы он просто показал, что вот мол запустил пример, вот результат, ошибка очевидно. Но нет - сухое "не решили".

Я проверил. Результат не обрадовал.
Mnior
Фиг с ним, kDnZP, вы то что никак не реагируете по основной задаче.

В итоге уже 2 дня срача прошли, а завтра можно уже самому взять скуль и все проверить и показать.
Но хрен же с этой задачей, намного ценнее не решить её конкретно, а научиться решать их все вообще. И исправлять свои неточности в понимании происходящего.

Ответ на основную задачу (как я ее понял вверху этого сообщения). Из данного обсуждения лично я вынес много полезного))). И это есть хорошо. Был еще один случай, обсуждения самого быстрого варианта накопительного итога... То, что это оказался курсор для меня было совершенно неожиданно, но факт есть факт. Надобно будет сравнить с 2012, но боюсь, что курсор опять победит.
21 май 12, 09:08    [12586225]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
* Уточнение.
Ответ должен был быть на другую ссылку:
Mnior
Хотя я ранее привёл нормальный скрипт 8147002. Ах нуда, он же читает посты по диагонали, упуская детали.

kDnZP
Я проверил. Результат не обрадовал.
21 май 12, 09:12    [12586236]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
kDnZP,

Не путайте ТСа еще больше :) По вашей же ссылке:
http://msdn.microsoft.com/en-us/library/ms131103
A user-defined table type cannot be passed as a table-valued parameter to, or be returned from, a managed stored procedure or function executing in the SQL Server process.
21 май 12, 09:27    [12586280]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
invm
kDnZP,

Не путайте ТСа еще больше :) По вашей же ссылке:
http://msdn.microsoft.com/en-us/library/ms131103
A user-defined table type cannot be passed as a table-valued parameter to, or be returned from, a managed stored procedure or function executing in the SQL Server process.

Мда... че-то проблемы у меня с внимательностью, вот что значит бегло прочитать и понять совершенно противоположное.
21 май 12, 09:35    [12586316]     Ответить | Цитировать Сообщить модератору
 Re: Передача табличной переменной в assembly процедуру  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
Вот, кстати, реализация split через рекурсию (благо вспоминать тут нечего):
DECLARE @tst1 NVARCHAR(MAX)
DECLARE @tst2 XML
DECLARE @limit INT=2048 -- <2048

SELECT	@tst1=Stuff((
SELECT  ','+LTRIM(STR(v1.number + v2.number * 2048))
FROM    master..spt_values v1
        INNER JOIN master..spt_values v2 ON v2.number < @limit
                                            AND v2.type = 'P'
WHERE   v1.type = 'P'
FOR XML Path(''),Type).value('text()[1]','VarChar(max)'),1,1,'')

;WITH rcte AS (
SELECT CAST(1 AS BIGINT) p, CHARINDEX(',',@tst1+',',1) p2, 1 id
UNION ALL
SELECT r.p2+1, CHARINDEX(',',@tst1+',',r.p2+1), r.id+1 FROM rcte r WHERE CHARINDEX(',',@tst1+',',r.p2+1)<>0
)
SELECT id, SUBSTRING(@tst1,p,p2-p) FROM rcte OPTION (MAXRECURSION 0)


/* -- Тут было что-то странное и непонятное, и тормознутое
;
WITH    q AS (SELECT    CAST(SUBSTRING(@tst1 + ',', 2, 2147483647) AS VARCHAR(MAX)) s
                       ,CAST(NULL AS INT) id
              UNION ALL
              SELECT    CAST(SUBSTRING(s, pos + 1, 2147483647) AS VARCHAR(MAX))
                       ,CAST(LEFT(s, pos - 1) AS INT)
              FROM      q
              CROSS APPLY (SELECT CHARINDEX (',', s) pos) t
              WHERE     pos > 0)
    SELECT  id
    FROM    q
    WHERE   id >= 0
OPTION  (MAXRECURSION 0)
*/

В оригинале 8147002 совсем уж странная рекурсия ИМХО, см. закомментированный блок.
21 май 12, 09:49    [12586374]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить