![]() |
#1 |
Участник
|
Denis Trunin's Blogs: Blocking in D365FO(and why you shouldn't always follow MS recommendations)
Источник: https://denistrunin.com//understanding-sql-blocking/
============== Understanding blocking is a key component of resolving performance issues. You can have fast CPU, a lot of memory, but if you face SQL blocking problem all these will not be fully utilized Источник: https://denistrunin.com//understanding-sql-blocking/
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
![]() |
#2 |
Moderator
|
Я просто добавлю, что update_recordset (точнее говоря - update в SQL Server) вешает блокировки не только на те записи, которые он реально обновляет, но и на те записи, которые попали в выборку по индексу. Ну то есть - если у нас подходящего индекса нету, то SQL может попробовать поискать по какому-то случайному индексу по dataAreaId, а перед поиском - попробуем все это ненадолго заблокировать. Плюс - иногда SQL Server переглючивает или индексы фрагментируются или еще что-то подобное случается, и оно выбирает план исполнения по не тому индексу. В этом случае тоже случаются аналогичные блокировки.
В то же время, если нам надо обновить не 100-200, а эдак 100K-200K записей, то особой альтернативы update_recordset просто нету. Да - есть вероятность блокировок. Да - надо строить правильные индексы. Да надо регулярно их перестраивать и строить статистику. Да -есть вероятность время от времени нарваться на блокировки. Но просто в каждом конкретном случае мы должны сравнивать риски больших задержек из за пошагового обновления и риски задержек из за взаимных блокировок. Плюс - я не уверен что во всех сценариях мы можем создавать отдельную транзакцию на каждое обновление. При этом если у нас одна большая транзация и обновление идет по одной записи в while select forupdate, то порядок обновления в разных кусках кода вполне может быть разным. (К слову сказать - в исходном примере вообще в while select не стоит order by, соответственно порядок обновления записей не является гарантированым...) Последний раз редактировалось fed; 31.01.2019 в 12:53. |
|
|
За это сообщение автора поблагодарили: mazzy (2), trud (5), Logger (5). |
![]() |
#3 |
Участник
|
Цитата:
ЗЫ: Еще они не используют find, а всегда перечисляют список полей, типа так еще быстрее ![]() |
|
|
За это сообщение автора поблагодарили: EVGL (15). |
![]() |
#4 |
Участник
|
Очень странно, вы нарушили две рекомендации (не делать длинных транзакций и иметь покрывающий индекс для where) чтобы показать, что тогда третья рекомендация не будет работать.
А дальше сомнительные, ничем не подкрепленный вывод: Цитата:
Try to avoid any update_recordset and delete_from usage by default(especially in document posting operations). Use it only when you are 100% sure that it will not cause blocking and you really need to reduce the operation time
Что вообще такое document posting ? И если вы уже говорите ut when someone tries to update the same table using a different set of fields(for example Field2 and Field4) we'll get blocking again., то используя ваш подход можно преположить, что любой кусок кода может быть использован кем-то дргуим как-то не так и надо быть к этому готовым! Т.е. все может стать document posting, чтобы это не было. ![]() |
|
![]() |
#5 |
Участник
|
|
|
![]() |
#6 |
Moderator
|
Я просто замечу что две первых рекомендации не всегда выполнимы. Если разносится большой документ, то на короткие транзации это не порезать. Кроме того - покрывающий индекс на каждую возможную комбинацию полей в where тоже не всегда доступен. Кроме того, как я уже написал, время от времени (особенно на квазивременных таблицах типа InventSumDeltaDim), SQL Server переглючивает и он выбирает неправильный индекс, даже если правильный покрывающий индекс присутствует.
|
|
![]() |
#7 |
Участник
|
ну это постинг любых документов, закупок, заказов журналов - там где это наиболее критично. т.е. кейс - нам надо обновить что-то в нашей таблице, когда происходит разноска
ну в общем случае select forupdate не блокируется.Исключение составляет эскаляция блокировок, но это уже другая тема Цитата:
Сообщение от skuull
![]() И если вы уже говорите ut when someone tries to update the same table using a different set of fields(for example Field2 and Field4) we'll get blocking again., то используя ваш подход можно преположить, что любой кусок кода может быть использован кем-то дргуим как-то не так и надо быть к этому готовым! Т.е. все может стать document posting, чтобы это не было.
![]() |
|
![]() |
#8 |
Участник
|
Цитата:
Сообщение от fed
![]() Я просто замечу что две первых рекомендации не всегда выполнимы. Если разносится большой документ, то на короткие транзации это не порезать. Кроме того - покрывающий индекс на каждую возможную комбинацию полей в where тоже не всегда доступен. Кроме того, как я уже написал, время от времени (особенно на квазивременных таблицах типа InventSumDeltaDim), SQL Server переглючивает и он выбирает неправильный индекс, даже если правильный покрывающий индекс присутствует.
![]() |
|
|
За это сообщение автора поблагодарили: ax_mct (3). |
![]() |
#9 |
Участник
|
Это та же самая тема. Вопрос эскалации встает при больших количествах данных\пользователей\потоков и говорить "тут больше 1-2х строк не будет" звучит не убидительно. Сегодня нет, а завтра поменяется бизнес процесс и их будет тысячи, что сядем все переписывать?
|
|
![]() |
#10 |
Moderator
|
Цитата:
А мы потом, по возможности, тоже поищем в нем ошибки и слегонца постебемся. ![]() |
|
![]() |
#11 |
Участник
|
Цитата:
Цитата:
![]() Подобный вопрос обычно задавали при завершении стажировки в Коламбусе - какой вариант быстрее 1 или 2 X++: CustTable custTable; ; //1 select AccountNum from custTable where custTable.AccountNum == "C-0000101"; custTable = null; //2 custTable = custTable::find("C-0000101"); |
|
![]() |
#12 |
Участник
|
Цитата:
![]() |
|
![]() |
#13 |
Участник
|
|
|
![]() |
#14 |
Banned
|
Цитата:
Сообщение от trud
![]() Ага, именно это и посыл поста, используем только когда нужно
Вы реально не знаете или это просто флуд? ![]() Подобный вопрос обычно задавали при завершении стажировки в Коламбусе - какой вариант быстрее 1 или 2 X++: CustTable custTable; ; //1 select AccountNum from custTable where custTable.AccountNum == "C-0000101"; custTable = null; //2 custTable = custTable::find("C-0000101"); |
|
![]() |
#15 |
Banned
|
|
|
![]() |
#16 |
Участник
|
Цитата:
![]() |
|
|
За это сообщение автора поблагодарили: trud (1). |
![]() |
#17 |
Участник
|
Ну главная идея была дать понять, что любую вещь связанную с производительностью надо проверять. Т.е. обычно отвечали что меньше полей, значит запрос меньше. А как посмотреть посмотреть запрос - ну включить трассировку - ну давай посмотрим... смотрим - они одинаковы
|
|
![]() |
#18 |
Участник
|
А вот тут можно подробнее, почему одинаково (пусть это уже и оффтоп)?
Вроде в случае когда у нас указан набор полей, у нас меньше количество данных передаваемых между клиентом-сервером, и поэтому работать должно быстрее? Best practicies опять же, настаивают именно на варианте "укажите в запросе конкретные нужные вам поля" |
|
![]() |
#19 |
Участник
|
Цитата:
Цитата:
А если переменную назвать не "custTable", а "с" будет быстрее? (сорри за стеб) А есть ссылка? |
|
![]() |
#20 |
Участник
|
![]() Цитата:
Сообщение от Pandasama
![]() А вот тут можно подробнее, почему одинаково (пусть это уже и оффтоп)?
Вроде в случае когда у нас указан набор полей, у нас меньше количество данных передаваемых между клиентом-сервером, и поэтому работать должно быстрее? Best practicies опять же, настаивают именно на варианте "укажите в запросе конкретные нужные вам поля" Видимо вам надо в коламбус на месяцок, подтянуть основы на стажеровочке ![]() Последний раз редактировалось skuull; 01.02.2019 в 08:42. |
|