22.11.2024, 13:24 | #21 |
Участник
|
Цитата:
А какие могут быть причины этого? И как проверить, что это действительно оно в следующий раз? |
|
21.01.2025, 12:42 | #22 |
Участник
|
Столкнулись с той же проблемой.
На временной TempDb табличке. Проблема появилась после того как в конфигурации аоса включили index hint. Вероятно у вас также включены index hint, поэтому одной из рекомендаций было бы отключить их. (это 1-й бит в узле hint в конфигурации аоса в реестре. Дефолтное значение там "2") Еще я заметил что помогает, если явно указать в запросе index имя индекса (но не index hint имя индекса) видимо это добавляет сортировку но подавляет кривой index hint. Но проблему решает. Вы как-нибудь решили для себя вопрос ? Последний раз редактировалось Logger; 21.01.2025 в 13:28. |
|
|
За это сообщение автора поблагодарили: Товарищ ♂uatr (4). |
22.01.2025, 18:29 | #23 |
Участник
|
Поразбирались еще в проблеме.
Что было у нас. Включили index hint в конфигурации аоса (ключ hint в реестре, поменяли значение с 2 на 3) После этого ядро стало ставить в запросах index hint там где они указаны в коде явно. А там, где явно в коде не указаны, ядро может подставить их по своему усмотрению в зависимости от условий фильтрации (если сочтет какой-либо индекс подходящим под условия). Или оставит бех хинтов. В общем, поведение как в Ax3.0 KR1 Правда там (в Ax3) был еще флажок 512 который позволял отключать автоматический подбор хинтов. Обсуждался тут : Кто использует KR3 ? Но в 2012-й он не работает. При попытке явно указать такой флаг конфигурационная утилита пишет что: Цитата:
An unsupported value for the hints option has been detected. The default value has been restored, which affects the following settings: - Allow INDEX hints in queries (off by default) - Include SUBSTR and LOWER in all SELECT statements to support Oracle mixed-case systems (off by default) - Include LTRIM in all SELECT statements to remove leading space from right-aligned columns (off by default). If you do not change the settings now, they will be saved with default values.
В конкретном запросе автоподбор хинта ядром можно подавить, указав index имя индекса тогда добавится сортировка по указанному индексу но хинтов не будет. Либо (как подсказал Glibs, за что ему respect) можно завести на табличке пустой выключенный индекс, например с именем NoHintIdx и указать его явно как хинта index hint NoHintIdx тогда никакого хинта не будет. Мы явно указали индексы хинт, поэтому ядро прекращает самодеятельность, но поскольку реального индекса такого в БД нет, то ничего не ставит. Про кривое формирование текста запроса, я заметил что в одних случаях запрос к времянке идет нормально с таким именем X++: SELECT TOP 1 ... FROM tempdb."DBO".t105707_0152F6081B43458B87857CD84D429941 T1 WITH ( INDEX(i105707_I_105707PHONEIDX_0152F6081B43458B87857CD84D429941)) WHERE ... X++: SELECT TOP 1 ... FROM tempdb."DBO".t105707_0152F6081B43458B87857CD84D429941 T1 WITH ( INDEX(i105707_I_105707PHONEIDX_(null))) WHERE ... Стали разбираться, оказалось что это происходит после вызова метода xRecord.linkPhysicalTableInstance(). Похоже linkPhysicalTableInstance переназначает в ядре ссылки с одной таблички на другую, но не все данные копирует правильно. Что-то остается непроинициализированным. И проявляется это не всегда, а только при стечении обстоятельств. А вот если для тех же целей воспользоваться парой методов xRecord.getPhysicalTableName() / xRecord.useExistingTempDBTable() то все хорошо. Хинты с правильными именами формируются. Поэтому сделали на SysDictTable свой метод и используем его вместо xRecord.linkPhysicalTableInstance() X++: /// <summary> /// _thisRecord начинает ссылаться на данные _record /// Метод сделан как замена стандартному xRecord.linkPhysicalTableInstance() чтобы обойти его ошибки. /// подробнее см. /// [url=https://axforum.info/forums/showthread.php?p=443440#post443440]Ax 2012 строит запрос с ошибкой в синтаксисе[/url] /// [url=https://axforum.info/forums/showthread.php?p=437193#post437193]Работа с TempDB-таблицами[/url] /// </summary> /// <param name="_thisRecord"> /// Таблица, у которой переназначаются данные. /// </param> /// <param name="_record"> /// Таблица, на чьи данные теперь будут ссылаться /// </param> /// <returns> /// Успешно или нет /// </returns> /// <remarks> /// /// </remarks> // CustCrmClientActivityDocTmp_MRC_Fix "Исправляем ошибку WITH ( INDEX(i105707_I_105707PHONEIDX_(null)))", PKoz3 22.01.2025 public static boolean linkPhysicalTableInstance_MRC(Common _thisRecord, Common _record) { Common tmpRecord; str tableName; boolean ret; ; tableName = _record.getPhysicalTableName(); if (!tableName) // значит табличку не сохраняли еще { tmpRecord = _record.data(); // см. RetailUtilities::getPhysicalTableName(_record); // Force instantiation of Temp DB table. select generateonly firstOnly RecId from _record; tableName = _record.getPhysicalTableName(); _record.data(tmpRecord); } ret = _thisRecord.useExistingTempDBTable(tableName); // ret = _thisRecord.linkPhysicalTableInstance(_record); // такой вариант вместо вызова useExistingTempDBTable() не работает // проверяли предположение что проблема была в том, что вызвали linkPhysicalTableInstance для непроинициализированного параметра // в котором еще нет физического имени таблицы (не в этом ли корень проблем ? Поэтому сперва принудительно инициализируем буфер, // чтобы вызов linkPhysicalTableInstance гарантированно шел на проинициализированном TempDb буфере) // Оказалось что нет - ошибка с хинтом воспроизводится после любого вызова linkPhysicalTableInstance // т.е. сам по себе linkPhysicalTableInstance - какой то кривой и что-то портит в xRecord, поэтому лучше // избегать вызовов linkPhysicalTableInstance return ret; } linkPhysicalTableInstance - вообще какой-то стремный и глючный. Работа с TempDB-таблицами Работа с TempDB-таблицами поэтому сделали еще проверку BP. Класс SysBPCheckMemberFunction добавили метод checkSourceLinkPhysicalTableInstance X++: /// /// <summary> /// Делаем запрет на вызов common.linkPhysicalTableInstance /// </summary> // CustCrmClientActivityDocTmp_MRC_Fix "Исправляем ошибку WITH ( INDEX(i105707_I_105707PHONEIDX_(null)))", PKoz 22.01.2025 protected boolean checkSourceLinkPhysicalTableInstance(xRefTmpReferences _thisRefererences) { boolean ret = true; ; while select _thisRefererences where _thisRefererences.Kind == xRefKind::TableInstanceMethod && _thisRefererences.Reference == XRefReference::Call && _thisRefererences.Name == methodStr(xRecord, linkPhysicalTableInstance) { this.addSuppressableError(#BPErrorTableLinkPhysicalTableInstance_MRC, // так удобнее _thisRefererences.Line, _thisRefererences.Column, strFmt(@'Вызов метода "%1.%2" лучше заменить на вызов метода %3::%4 Подробности в исходном коде %3::%4.', _thisRefererences.ParentName, // 1 _thisRefererences.Name, // 2 classStr(SysDictTable), // 3 staticMethodStr(SysDictTable, linkPhysicalTableInstance_MRC) // 4 ) ); ret = false; } return ret; } |
|
|
За это сообщение автора поблагодарили: raz (10). |
28.01.2025, 12:31 | #24 |
Участник
|
Все что описал выше мы пробовали на
kernel 6.3.6000.8144 Взял последний доступный kernel 6.3.6000.11008 все то же самое. Бага не исправлена. Обходной путь с заменой xRecord.linkPhysicalTableInstance() на SysDictTable::linkPhysicalTableInstance_MRC() решает вопрос. |
|
28.01.2025, 19:55 | #25 |
Administrator
|
Ну... громко сказано, что это бага... Бага, которая проявляется при активации режима, от которого отказались (причем включение режима тоже нетривиальная штука) - багой не считается ))
А если серьезно - я считаю, что каждый софт должен заниматься своим делом. Не задача SQL Server считать бизнес-логику. Не дело АХ - указывать БД какой индекс брать.
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: Товарищ ♂uatr (1). |
Теги |
index hint, linkphysicaltableinstance |
|
|