Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Коллеги, есть проблема производительности при конкатенации значений в переменную nvarchar(max) Вот смотрите: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. Если в строчке с присвоением внутри цикла указывать не 'ffffffffffffffffffffffffffffff', а 'ffff' (т.е. просто меньшее кол-во символов) - то производительность запроса изменяется в разы. То есть явное линейное падение производительности. Это что же, сиквел при такой конкатенации вытаскивает все в память, выполняет операцию, а затем опять скидывает в кэш/на диск. Т.е. не просто добавляет нужные символы к уже висящей в памяти переменной? Собственно вопроса два: 1. Почему так происходит? (можете просто ссылкой кинуться в меня) 2. А есть ли альтернативные способы такой конкатенации? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 11:43 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Ну в данном конкретном случае чего бы не попользовать REPLICATE()... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 11:50 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Дополнение: varchar(max) работает в разы быстрее nvarchar(max) а nvarchar(4000) в десятки раз быстрее nvarchar(max) Но мне нужна длинная строчка ((( порядка около 500 тыс. символов по итогу ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 11:51 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
AkinaНу в данном конкретном случае чего бы не попользовать REPLICATE()... Да нет, в реальном то запросе там разные значения будут... Это я для экспериментов в чистых условиях такой запрос наваял. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 11:52 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Тогда покажите все условия чтобы планируете реализовать через такую логику. Может там цикл и не нужен будет ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:02 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
вы изучали какой нибудь язык программирования, который "в ручную" работает с памятью? )) понимаете чем отличается char,nvarchar типы? эти вопросы для того что, бы понять куда вас "ткнуть пальцем" )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:06 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Да, я знаю особенности и различия char/nchar/varchar/nvarchar/max... В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных. Но просадка по производительности именно в конкатенации. Условия которые не обойти: - не уложится в 4000 или в 8000 символов (даже внутри каждой итерации) Сейчас нашел еще одно решение: вместо конкатенации вставляю значения во временную табличку, а затем из накопленных там строк формирую итоговую строчку. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Работает заметно быстрее, даже на значительно больших количествах строк. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:13 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Код: sql 1. 2. P.S. Если не хотите писать N перед строками, то не используйте юникодный тип. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:14 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Big17Да, я знаю особенности и различия char/nchar/varchar/nvarchar/max... В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных. Но просадка по производительности именно в конкатенации. Условия которые не обойти: - не уложится в 4000 или в 8000 символов (даже внутри каждой итерации) Сейчас нашел еще одно решение: вместо конкатенации вставляю значения во временную табличку, а затем из накопленных там строк формирую итоговую строчку. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Работает заметно быстрее, даже на значительно больших количествах строк.А зачем удаляете первый символ? Вы же перед строкой ничего не добавляете! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:18 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Big17 [src]В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных. Но просадка по производительности именно в конкатенации. Покажите... ибо не понятна суть задачи что вы решаете. То что написано решается через REPLICATE. А делать замеры скорости дело неблагодарное для абстрактных задач. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:19 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
N перед литералами практически не влияет на производительность в моем случае ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:19 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
AlanDentonBig17 [src]В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных. Но просадка по производительности именно в конкатенации. Покажите... ибо не понятна суть задачи что вы решаете. То что написано решается через REPLICATE. А делать замеры скорости дело неблагодарное для абстрактных задач. Да нет, в реальном то запросе там разные значения будут... Это я для экспериментов в чистых условиях такой запрос наваял. В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:20 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Big17N перед литералами практически не влияет на производительность в моем случаеВлияет на корректность преобразования VARCHAR() в NVARCHAR(). При чём здесь производительность? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:22 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Big17В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных.А по курсору-то циклом, небось, гуляете? Прямой связи между циклом и курсором нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:24 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Big17Да, я знаю особенности и различия char/nchar/varchar/nvarchar/max... В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных. Но просадка по производительности именно в конкатенации. Условия которые не обойти: - не уложится в 4000 или в 8000 символов (даже внутри каждой итерации) Сейчас нашел еще одно решение: вместо конкатенации вставляю значения во временную табличку, а затем из накопленных там строк формирую итоговую строчку. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Работает заметно быстрее, даже на значительно больших количествах строк. таки не ответили на вопрос про языки программирования и работу с памятью ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 12:43 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Big17, Суммирование строк ваще тяжелая операция - зависит от способа организации строковых данных. Это перегоняется масса байтов. Каждый раз при суммировании резервируется новый участок памяти и туда пузырятся обе строки. И если это в цикле - получается кошмар в цикле. В VB.NET и с# для ускорения/оптимизации этой операции создан спецкласс StringBuilder. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 14:12 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. Это что же, сиквел при такой конкатенации вытаскивает все в память, выполняет операцию, а затем опять скидывает в кэш/на диск. О чём ты, какой диск ? тут нет никаких операций с диском вообще. Всё в памяти. Т.е. не просто добавляет нужные символы к уже висящей в памяти переменной? Именно так. Собственно вопроса два: 1. Почему так происходит? (можете просто ссылкой кинуться в меня) 2. А есть ли альтернативные способы такой конкатенации? 1) потому. 2) нет. У тебя просто происходит квадратичный взрыв объёма данных. 10000 * length('ffffffffffffffffffffffffffffff') (или length('ffff') ), 4 и 30. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2018, 23:39 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Big17В реальной задаче у меня конечно же не цикл, а курсор, который формирует итоговый набор данных.Курсор без цикла? Ооооо. :-) Попытайтесь переделать ваш цикл в запрос, тогда будет быстрее, может быть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.03.2018, 08:46 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
alexeyvgПопытайтесь переделать ваш цикл в запрос, тогда будет быстрее, может быть. Ой, не заметил, вы уже нашли: Big17Сейчас нашел еще одно решение: вместо конкатенации вставляю значения во временную табличку, а затем из накопленных там строк формирую итоговую строчку. Да, или так, или вообще вот это "формирую" сразу делать из исходных данных, без вставки во временную табличку. Так сказать, работать с РСУБД именно как с РСУБД, операциями над множествами на платформе, созданной для этих операций. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.03.2018, 08:50 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Вместо цикла рекурсивное CTE не пробовали? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2018, 12:14 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
лоллВместо цикла рекурсивное CTE не пробовали?Он уже нашёл вариант лучше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2018, 12:45 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Massa52Big17, Это перегоняется масса байтов. Каждый раз при суммировании резервируется новый участок памяти и туда пузырятся обе строки. И если это в цикле - получается кошмар в цикле. В VB.NET и с# для ускорения/оптимизации этой операции создан спецкласс StringBuilder. Это потому что в дотнете класс string - immutable, и конкатенация порождает новый экземпляр. В прочих случаях (например, в том же MSSQL) всё может быть совсем иначе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2018, 14:45 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Конкатенация в памяти Windows намного медленнее конкатенации на диске. Use it wisely. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2018, 19:06 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
[quot Сон Веры Павловны]Massa52Big17, Это потому что в дотнете класс string - immutable, и конкатенация порождает новый экземпляр. В прочих случаях (например, в том же MSSQL) всё может быть совсем иначе. http://www.sqlservercentral.com/blogs/philfactor/2009/02/16/be-careful-with-string-concatenations-in-sql-server-with-big-strings/ Posted by RBarryYoung on 18 February 2009 It has long been known that naive linear string concatenation is an O(n^2) operation (more specifically, it's triangular). That simple fact is one of the big reasons that .NET has the StringBuilder class (which uses the strings->array->mass_concatenate trick that peter alludes to). As it happens, I spent quite a lot of time last month investigating this problem and potential solutions and let me just say: it's tough in SQL. Here are the problems: 1) SQL Server apparently (based on my tests) already does the "buffer-extension" trick available to mutable strings. Unfortunately, the Extension trick does NOT solve the O(n^2) problem, it just partially alleviates it at the lower end because some percentage(k) of appends can be extensions instead of creating a new string. Effectively it changes the {(n)*(n+1)/2} cost of the naive implementation to {n +(n)*(n-1)/(2*k)} where "k" is that percentage. It's better, but it's still O(n^2). 2) The "array & mass-concatenate" trick is not available to T-SQL, not because SQL doesn't have arrays (tables serve the same purpose), but because AFAIK, there is no function that can take a variable "collection" of strings (table, array, whatever) and produce an output string. 3) The "pre-allocate and Stuff" trick popular with mutable strings is not workable in T-SQL because the STUFF() function in T_SQL is NOT like the function of the same name in some general purpose languages: the T-SQL STUFF() is an RHS (right-hand side) function and NOT an LHS (left-hand side) function. AFAIK, there is no function in SQL that can (physically) write into a pre-existing string. That all said, I did eventually find a way to do it. Not in the O(n) time (linear) achievable in most general purpose languages, but I could get it down to O(n*Log(n)) time which is still a huge improvement. Unfortunately, I do not have it together in a presentable form and it would take me some time to do so (a day or so), but I can get it to you if you want. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2018, 03:20 |
|
||
|
Конкатенация большого количества значений
|
|||
|---|---|---|---|
|
#18+
Massa522) The "array & mass-concatenate" trick is not available to T-SQL, not because SQL doesn't have arrays (tables serve the same purpose), but because AFAIK, there is no function that can take a variable "collection" of strings (table, array, whatever) and produce an output string. Дело не в отсутствии массивов - их вполне, начиная с 2008-й версии, можно заменить на UDTT, и написать свою функцию для конкатенации (другой вопрос, зачем это нужно, если посредством cross/outer apply можно прицепить конкатенацию через for xml path). Просто этот дотнетовский "array & mass-concatenate" trick - вовсе не trick: в StringBuilder в итоге конкатенация небольших объемов сводится к unsafe операциям с указателями, а на больших - вызывается managed-аналог сишного memmove (тоже, разумеется, unsafe). Т.е. сводится к прямой работе с памятью, которая, разумеется, в T-SQL недоступна. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2018, 06:57 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=39624333&tid=1690000]: |
0ms |
get settings: |
6ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
24ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
64ms |
get tp. blocked users: |
1ms |
| others: | 218ms |
| total: | 346ms |

| 0 / 0 |
