AXForum  
Вернуться   AXForum > Microsoft Dynamics NAV > NAV: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 28.09.2007, 08:43   #21  
smoyk is offline
smoyk
Участник
 
188 / 13 (1) ++
Регистрация: 20.04.2007
По поводу блокировок пока ничего не могу сказать, сейчас как раз разбираюсь, как это работает (на практике так сказать)...
Да и по поводу многих пунктов из списка golyshev'а не все понятно.
Но вот по поводу SETCURRENTKEY я не совсем согласен. Чтобы наиболее эффективно использовать SETFILTER и SETRANGE насколько я знаю есть такая рекомендация: надо сделать активным ключ из полей, по которым накладывается фильтрация и накладывать фильтры на поля желательно в порядке их расположения в этом ключе. Разве не так?
Старый 28.09.2007, 12:46   #22  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
Цитата:
Сообщение от smoyk Посмотреть сообщение
Разве не так?
Это верно только для нативной базы.
Для SQL это не верно.

MS SQL Server самостоятельно выбирает ключи поиска и план выполнения запроса. Независимо от переданного ему ключа через функцию SETCURRENTKEY

пример:

Код:
recCustLedgerEntry	Record	Cust. Ledger Entry	
________________________________________
recCustLedgerEntry.RESET;
recCustLedgerEntry.SETCURRENTKEY("Customer No.","Posting Date","Currency Code");
recCustLedgerEntry.SETRANGE("Customer No.",'C3438');
recCustLedgerEntry.SETRANGE("Posting Date",231106D);
recCustLedgerEntry.SETRANGE("External Document No.",'03');
recCustLedgerEntry.FIND('-');
Этот код приведет к выполнению следующего SQL запроса:
Код:
SELECT  * FROM "dbo"."КРОК$Cust__Ledger_Entry" 
WHERE (("External_Document_No_"='03')) 
  AND (("Customer_No_"='C3438')) 
  AND (("Posting_Date"='2006-11-23')) 
ORDER BY "Customer_No_","Posting_Date","Currency_Code","Entry_No_"
Данный запрос будет выполнен по следующей схеме:

Параметры, переданные через SETCURRENTKEY, трактуется исключительно как порядок сортировки полученного результата (поле ORDER BY) и никак не влияют на выбор ключей, используемых при поиске.

Изменим вышеприведенный код, убрав из него вызов SETCURRENTKEY:
Код:
recCustLedgerEntry	Record	Cust. Ledger Entry	
________________________________________
recCustLedgerEntry.RESET;
recCustLedgerEntry.SETRANGE("External Document No.",'SCI_604983/SZ622586');
recCustLedgerEntry.SETRANGE("Posting Date",200906D);
recCustLedgerEntry.SETRANGE("Customer No.",'C3137');
recCustLedgerEntry.FIND('-');
Этот код приведет к выполнению SQL запроса:
Код:
SELECT  * FROM "dbo"."КРОК$Cust__Ledger_Entry" 
WHERE (("External_Document_No_"='03')) 
  AND (("Customer_No_"='C3438')) 
  AND (("Posting_Date"='2006-11-23')) 
ORDER BY "Entry_No_"
Сортировка в данном случае будет произведена по умолчанию, то есть по первичному ключу «Entry No.».

План выполнения запроса выглядит следующим образом:

Данный план выполнения лучше предыдущего, поскольку в нем отсутствует трудоемкая задача – сортировка конечного результата (сортировка входит в этап join’а таблиц).

Последний запрос в среднем в 5-10 раз быстрее первого (зависит от размеров таблицы)
Старый 01.10.2007, 12:40   #23  
Critic is offline
Critic
Участник
Аватар для Critic
 
13 / 10 (1) +
Регистрация: 17.03.2006
1) golyshev, а вы с какой версией навика работаете? Роботают ли ваши рекомендации для версии 3.60 (3.70А) ?
2) судя по
Код:
recCustLedgerEntry.RESET;
recCustLedgerEntry.SETRANGE("External Document No.",'SCI_604983/SZ622586');
recCustLedgerEntry.SETRANGE("Posting Date",200906D);
recCustLedgerEntry.SETRANGE("Customer No.",'C3137');
recCustLedgerEntry.FIND('-');
и
Код:
SELECT  * FROM "dbo"."КРОК$Cust__Ledger_Entry" 
WHERE (("External_Document_No_"='03')) 
  AND (("Customer_No_"='C3438')) 
  AND (("Posting_Date"='2006-11-23')) 
ORDER BY "Entry_No_"
SQLю вообще ровно на положение SETRANGE в коде навика или все-таки этим можно повлиять на ускорение обработки?
__________________
Ведрусса. Я не волшебник, а только учусь
Старый 01.10.2007, 13:58   #24  
MSI is offline
MSI
Участник
 
25 / 10 (1) +
Регистрация: 03.10.2006
Честно говоря, наблюдал массу вещей под сиквелем, кот. слабо укладываются в понимание. Например, что списочная форма, отображающая отфильтрованную большую таблицу с установленным ключом, отличным от первичного невероятно тупит при навигации. Стоит для уже отвильтрованного рекордсета выставить первичный ключ - работа формы становится много быстрее. Насчет выставления ключа тоже не все столь однозначно: есть пример отчетов, которые работает по разному в зависимости от выставленного ключа, причем с ключом они работают значительно быстрее, чем без него. Это немного неукладывается со сказанным в посте выше. Прихожу к выводу, что по наву под сиквелем все очень не однозначно, и на постоянно возникающие вопросы никакие SQL troubleshooting referencы не дают ответов....
Старый 01.10.2007, 16:14   #25  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
Цитата:
Сообщение от Critic Посмотреть сообщение
1) golyshev, а вы с какой версией навика работаете? Роботают ли ваши рекомендации для версии 3.60 (3.70А) ?
2) судя по
Код:
recCustLedgerEntry.RESET;
recCustLedgerEntry.SETRANGE("External Document No.",'SCI_604983/SZ622586');
recCustLedgerEntry.SETRANGE("Posting Date",200906D);
recCustLedgerEntry.SETRANGE("Customer No.",'C3137');
recCustLedgerEntry.FIND('-');
и
Код:
SELECT  * FROM "dbo"."КРОК$Cust__Ledger_Entry" 
WHERE (("External_Document_No_"='03')) 
  AND (("Customer_No_"='C3438')) 
  AND (("Posting_Date"='2006-11-23')) 
ORDER BY "Entry_No_"
SQLю вообще ровно на положение SETRANGE в коде навика или все-таки этим можно повлиять на ускорение обработки?
1) Мы работаем в 4.0, но это верно для 3.6 и 3.7
2) не понял суть вопроса. SETRANGE - это поле WHERE в SQL запросе, SETCURRENTKEY - это поле ORDER by в SQL запросе.

Цитата:
Сообщение от MSI Посмотреть сообщение
Честно говоря, наблюдал массу вещей под сиквелем, кот. слабо укладываются в понимание. Например, что списочная форма, отображающая отфильтрованную большую таблицу с установленным ключом, отличным от первичного невероятно тупит при навигации. Стоит для уже отвильтрованного рекордсета выставить первичный ключ - работа формы становится много быстрее. Насчет выставления ключа тоже не все столь однозначно: есть пример отчетов, которые работает по разному в зависимости от выставленного ключа, причем с ключом они работают значительно быстрее, чем без него. Это немного неукладывается со сказанным в посте выше. Прихожу к выводу, что по наву под сиквелем все очень не однозначно, и на постоянно возникающие вопросы никакие SQL troubleshooting referencы не дают ответов....
Безусловно, убирать SETCURRENTKEY в местах, где он влияет на бизнес-логику нельзя
(например кодеюнит коррекции себестоимости. Чтобы его ускорить и отказаться от SETCURRENTKEY мы его сильно переписали)

Конечно, есть ситуации, когда указание ключа ускоряет запрос. Каждый случай надо рассматривать индивидуально.

Но если понять почему происходит ускорение, то зачастую становится ясно, что быстрее всё равно будет с сортировкой по первичному ключу. Надо лишь подточить запрос.

Чаще всего это касается списочных форм на большой таблице.

Вот пример:
Форма на 17 таблице (Фин Журнал) с наложенными фильтрами по Posting Date, G/L Account No.,Debit Amount
Сортировка по первичному ключу - Entry No.

Предположим, Вы первый раз открыли форму, navision при этом открывает курсор, следующим запросом:

Код:
SELECT  * FROM "dbo"."КРОК$G_L_Entry" WITH (READUNCOMMITTED)  WHERE (("Posting_Date"=@P1)) AND (("Debit_Amount"<>@P2)) AND (("G_L_Account_No_"=@P3)) AND  "Entry_No_">=@P4 ORDER BY "Entry_No_" OPTION (FAST 5)
План запроса, который будет использован в данном случае сильно зависит от конкретного параметра, переданного в @P4.

Предположим, что @P4 большое число - т.е. форма позиционируется на последних записях.
При этом план запроса будет наверняка Clustered index Seek - т.е. поиск по первичному ключу.

План запроса при этом кешируется, и будет использован для всех запросов, независимо от переданных параметров.
Таким образом, в следующий раз, когда мы откроем форму, и спозиционируемся на первых записях, согласно уже скомпилированному плану, выборка будет идти по кластерному индексу. А так как @P4 у нас маленькое число, то SQL Server просканирует практически всю таблицу.

Если же на форме установить сортировку по Posting Date, то запрос будет
Код:
SELECT  * FROM "croc_na"."dbo"."КРОК$G_L_Entry" WITH (READUNCOMMITTED)  WHERE (("Posting_Date"=@P1)) AND (("Debit_Amount"<>@P2)) AND (("G_L_Account_No_"=@P3)) AND  "Posting_Date"=@P4 AND "Entry_No_">=@P5 ORDER BY "Posting_Date","Entry_No_" OPTION (FAST 5)
SQL server при этом, чтобы скомпенсировать затраты на сортировку, скорее всего выберет ключ G_L_Account_No_,Posting_Date.
И запрос будет выполняться одинакого быстро как для больших @P5 так и для маленьких.


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

Если создать plan guid для первого запроса, запретив SQL Server'у делать Clutered Index Seek, план построится таким образом, что скорость запроса будет относительно независима от параметров и быстрее второго случая (т.к. в нем будет отсутсвовать сортировка). Скорее всего это будет выборка по ключу G_L_Account_No_,Posting_Date с джоином выборки по кластерному индексу и без сортировки.

Код:
sp_create_plan_guide 
@name =  N'PlanGuid1',
@stmt = 
N'SELECT  * FROM "dbo"."КРОК$G_L_Entry" WITH (READUNCOMMITTED)  WHERE (("Posting_Date"=@P1)) AND (("Debit_Amount"<>@P2)) AND (("G_L_Account_No_"=@P3)) AND  "Entry_No_">=@P4 ORDER BY "Entry_No_" OPTION (FAST 5)',
@type = N'SQL',
@module_or_batch = NULL,
@params = N'@P1 datetime,@P2 decimal(38,20),@P3 varchar(20),@P4 int',
@hints = N'OPTION (OPTIMIZE FOR (@P4 = 0))'
Повторюсь - каждый случай индивидуален
Старый 01.10.2007, 19:51   #26  
MSI is offline
MSI
Участник
 
25 / 10 (1) +
Регистрация: 03.10.2006
Получается, что стандартный функционал без переписывания не имеет шансов работать с большими базами и относительно большим количеством пользователей (~100)?
Старый 01.10.2007, 21:47   #27  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
Зависит от используемых модулей и серверного оборудования.

Моё имхо - простая дистрибуция скрипя потянет при несколько-процессорном сервере с ~4gb озу и нормальным RAID'ом

На форуме писалось о технических ограничениях.
вот на вскидку:
http://forum.mazzy.ru/index.php?showtopic=...l=пользователей
Оборудование для Navision

Что касается нас - самое масштабное внедрение:
250-300 конкурентных пользователей
Сильно переделанный функционал (как на стороне NAV так и на стороне SQL)
Репликации, всяческие интеграции и прочее.
16-ти процессорный сервер IBM с 16GB ОЗУ и RAID'ом от EMC:CLARiiON
Часть пользователей висит на ферме Citrix серверов.
Старый 02.10.2007, 07:58   #28  
Critic is offline
Critic
Участник
Аватар для Critic
 
13 / 10 (1) +
Регистрация: 17.03.2006
Цитата:
2) не понял суть вопроса. SETRANGE - это поле WHERE в SQL запросе, SETCURRENTKEY - это поле ORDER by в SQL запросе.
логика бухгалтерии: А+Б<>Б+А

а по теме
Код:
recCustLedgerEntry.RESET;
recCustLedgerEntry.SETRANGE("External Document No.",'SCI_604983/SZ622586');
recCustLedgerEntry.SETRANGE("Posting Date",200906D);
recCustLedgerEntry.SETRANGE("Customer No.",'C3137');
recCustLedgerEntry.FIND('-');
и
Код:
recCustLedgerEntry.RESET;
recCustLedgerEntry.SETRANGE("Customer No.",'C3137');
recCustLedgerEntry.SETRANGE("External Document No.",'SCI_604983/SZ622586');
recCustLedgerEntry.SETRANGE("Posting Date",200906D);
recCustLedgerEntry.FIND('-');
для SQL будет единой обработкой или он попытается подстроиться под порядок написанного кода?

Что из параметров WHERE
Код:
(("External_Document_No_"=''SCI_604983/SZ622586'')) 
(("Customer_No_"='C3137')) 
(("Posting_Date"='200906D'))
SQL выберет первым для проверки?
__________________
Ведрусса. Я не волшебник, а только учусь
Старый 03.10.2007, 18:23   #30  
MSI is offline
MSI
Участник
 
25 / 10 (1) +
Регистрация: 03.10.2006
Находясь в состоянии борьбы за производительность нава под сиквелем у меня (уверен что ни только у меня ) возник ряд вопросов, в поиске ответов на которые мне любезно помог господин Golyshev. Даные вопросы могут оказаться интересными и для других участников форума. Господину Golyshev - огромное спасибо.


Цитата:
Цитата:
Сталкиваюсь со следующей проблемой: списочные формы больших таблиц иногда просто подвисают намертво при открытии (если стоит сортировка не по первичному ключу). Т.е. форма открывается, белеет, и нав пишет что не отвечает. И не выходит из этого состояния. (!!!) Особенно этот эффект неприятен при DrillDown во FlowFields, где выбором ключа какими-то средствами разработки Нава сложно управлять. Кстати, до конца не уверен, но есть ощущение, что ситуации не возникает, если для ключа отключена опция MaintainSQLIndex, т.е. формы никудышно работают именно с SQL-ными ключами.
Если Вы отключите MaintainSQLIndex у всех ключей - система умрет.
На всех больших таблицах (17,32, 5802 и т.п.) нужно очень тщательно подобрать ключи, для которых необходим MaintainSQLIndex и правильно установить для них SQLIndex

Проблема со списочными формами - это как раз проблема, описанная мной в примере (про 17 таблицу)
Для этих форм везде надо установить ключ по умоланию в первичный (св-во SourceTableView)

Цитата:
И еще один вопрос, который может показаться странным, но ситуация имеет место быть: иногда при прекращении работы учетных кодъюнитов по ERROR сиквель "забывает" решить, что транзакция завершена и снять блокировки с таблиц кот. были заблокированны до момента как (!) пользователь не нажмет ок на ERROR. В то время как все мануалы четко утверждают о том, что, дескать, все сообщения выводятся после завршения транзакции.

Если есть опыт борьбы с такой ситуацией очень бы хотелось получить какие-то рекомендации. Заранее благодарю.
Не знаю какие мануалы вы читали, но в NAV Installation & Configuration четко написано, что транзакция отказывается только ПОСЛЕ того, как пользователь нажмет ОК. И с этим прийдется смириться.

Мы боролись с этим так: скрипт, запускаемый каждые 15 секунд, проверяет - если какой-то пользователь является причиной блокировки и не посылает команды на сервер в течении 15 секунд, мы его отключаем.

P.S. Думаю наш диалог будет полезен и другим участникам форума. Если Вам не принципиально, я бы рекомендовал публичное обсуждение
PS Еще очень бы хотелось услышать про правильную установку SQLIndex для ключей со свойством MaintainSQLIndex, установленном в TRUE
Старый 03.10.2007, 19:16   #31  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
Вот рекомендации, разработанные мной для наших разработчиков и подходящие для OLTP баз.

По умолчанию рекомендуется устанавливать поле MaintainSQLIndex в значение No, изменяя это значение только после того, когда станет ясно, что необходим дополнительный индекс в СУБД для таблицы и какие именно поля необходимо в него включить. (Анализируется Profiler'ом)

Большинство таблиц (а соответственно и индексов) создавались на ранних версиях Navision Attain, и были рассчитаны на работу с собственной СУБД. Скорее всего, именно этот факт является причиной того, что в существующей версии Navision (3.60 – 4.00 SQL Option) большое количество индексов построено по принципам, не учитывающим специфику MS SQL.
  1. Короткий индекс лучше чем длинный

    Перед выполнением любого запроса MS SQL строит план, согласно которому будет выполняться запрос. При построении плана сервер выбирает индексы, которые будут использованы и в зачастую использует в именно короткие индексы.

    Короткие индексы, в отличие от длинных индексов:
    • * Легче в обслуживании, что увеличивает производительность операций записи.
      * Универсальны, так как MS SQL не выполняет запросы «в лоб» а использует объединение нескольких подзапросов.
      * Суммарное количество необходимых в таблице индексов уменьшается.
    Оптимальными являются индексы, состоящие из одного или двух полей, разбивающие таблицу на примерно равные порции маленького размера.

    Пример:
    Таблица 17 - G/L Entry содержит 2 ключа
    1. Agreement No.
    2. Agreement No.,Posting Date,Source Type,G/L Account No.,Source No.

    Второй индекс слишком длинный, нужно либо использовать его сокращенную форму, либо вовсе отключить. Для того чтобы определить, нужно ли отключать второй индекс, нужно определить, достаточно ли одного индекса «Agreement No.».

    Для этого посмотрим, как разбивает поле «Agreement No.» таблицу «G/L Entry», выполнив запрос
    Код:
    select count(*),"Agreement_No_"
    from "dbo"."КРОК$G_L_Entry"
    group by "Agreement_No_"
    Если результат запроса покажет, что поле «Agreement No.» разбивает таблицу на большое число порций малого объема (в среднем 1-100 записей в каждой порции). Это показатель того, что поле «Agreement No.» можно использовать в качестве ключа, не привлекая второе поле. Таким образом, второй ключ можно отключить от обслуживания в MS SQL.
  2. Первое поле индекса бьет, второе - добивает
    При создании индекса из двух элементов, нужно выбирать поля таким образом, чтобы первое поле разбивало таблицу на порции средним объемом 0.1%-0.5% от общего размера таблицы, а оба поля разбивали таблицу на порции средним объемом в 1-100 записей. Например, таблица «Value Entry», ключ «Item No., Posting Date»

    Типичным для Navision является наличие поля типа Option в качестве первого поля индекса. Например, индекс таблицы «Sales line» - «Document Type, Bill-to Customer No., Currency Code».

    MS SQL при построении плана выполнения запроса старается выбирать индексы поиска таким образом, чтобы после фильтрации по первому полю индекса осталось как можно меньше записей. Индексы, имеющие первым полем Option или Boolean не эффективны – они разбивают таблицу на несколько больших порций, а не много маленьких.

    Правда, существует исключение из этого правила, когда ключ с полем Boolean или Option разбивает таблицу крайне не равномерно и зачастую требуется получить меньшую часть этого разбиения. Например, ключ таблицы «Cust. Ledger Entry» - «Open, Due Date». Это полезный ключ, потому что часто возникает необходимость получить открытые операции и только маленькая часть всех операций будет открыта.
  3. Оптимизация под OLTP
    Нужно иметь в виду, что каждый создаваемый индекс, особенно состоящий из большого количества полей, снижает производительность операций INSERT, MODIFY, DELETE производимых над таблицей. Зачастую бывает выгоднее отключить индекс, потеряв немного производительности в чтении, и получив прирост производительности операций записи.

    Большинство таблиц Navision, связанных с хранением учетной информации, лучше оптимизировать под операции записи. Например, для таблиц «Item Ledger Entry», «Value Entry», «Cust. Ledger Entry» следует отключать от обслуживания более половины ключей. Их редкое использование не является аргументом в пользу потери производительности при учете документов.
Вот пример оптимизации некоторых ключей из таблицы Item Ledger Entry
ключ «Item No.», «Variant Code», «Drop Shipment», «Location Code», «Posting Date»
Этот ключ слишком длинный, для того чтобы делать из него индекс в MS SQL (правило 1). Определим, из каких полей должен состоять индекс MS SQL – для этого посмотрим, каким образом разбивается таблица по приведенным полям.

Выполнение следующего запроса выдаст разбиение по «Item No.»:
Код:
select count(*),"Item_No_"
from "dbo"."КРОК$item_Ledger_Entry"
group by "Item_No_"
Предположим, разбиение получается достаточно большим, однако по популярным товарам объем разбиения получается в районе 200 записей. Согласно правилу 2, нужно подобрать второе поле индекса, которое даст достаточное измельчение данного разбиения. Переберем возможные варианты:
Код:
select count(*),"Item_No_","Variant_Code"
from "dbo"."КРОК$item_Ledger_Entry"
group by "Item_No_","Variant_Code"
Код:
select count(*),"Item_No_","Drop_Shipment"
from "dbo"."КРОК$item_Ledger_Entry"
group by "Item_No_","Drop_Shipment"
Код:
select count(*),"Item_No_","Location_Code"
from "dbo"."КРОК$item_Ledger_Entry"
group by "Item_No_","Location_Code"
Код:
select count(*),"Item_No_","Posting_Date"
from "dbo"."КРОК$item_Ledger_Entry"
group by "Item_No_","Posting_Date"
Первые два варианта не подходят, поскольку измельчение не увеличивается достаточно сильно – среднее количество записей в разбиении по прежнему около 200.

Последние два варианта – разбиение по «Item No.»+«Location Code» и «Item No.»+«Posting Date» - удовлетворяют правилу 2. и могут быть использованы в качестве индекса.

Аналогично оптимизируются и остальные индексы таблицы «Item Ledger Entry». После подобных манипуляций, из 30 длинных ключей Navision обслуживаются лишь 10 коротких. Это существенно увеличивает скорость записи и модификации таблицы, что в свою очередь увеличивает скорость учетных операций.
Кроме того, при выборках в коде по этой таблице, не будет неоднозначностей по поводу того, какой именно индекс будет использовать MSSQL (главное не забывать НЕ указывать SETCURRENTKEY).
Старый 09.10.2007, 11:05   #32  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Цитата:
Сообщение от golyshev Посмотреть сообщение
Кроме того, при выборках в коде по этой таблице, не будет неоднозначностей по поводу того, какой именно индекс будет использовать MSSQL (главное не забывать НЕ указывать SETCURRENTKEY).
Запускаю вот такой код с включенным Монитором Клиента.
[codebox]
TT := TIME;
GLEntry.RESET;
//GLEntry.SETCURRENTKEY("G/L Account No.");
GLEntry.SETRANGE("G/L Account No.",'20.70');
IF GLEntry.FIND('-') THEN;
MESSAGE('ok %1',TIME - TT);[/codebox]

Время выполнения запроса - 4407ms. В Мониторе вижу, что SQL Plan = Clustered Index Scan(Test$G_L Entry$0)[3,1], SQL Index = "Операция Но.".

Далее делаю так:
[codebox]
TT := TIME;
GLEntry.RESET;
GLEntry.SETCURRENTKEY("G/L Account No.");
GLEntry.SETRANGE("G/L Account No.",'20.70');
IF GLEntry.FIND('-') THEN;
MESSAGE('ok %1',TIME - TT);[/codebox]

Время выполнения - 47ms. SQL Plan = Bookmark Lookup[3,1];Index Seek($1)[4,3], SQL Index = "Фин. Счет Но., Дата Учета, Операция Но.".

Т.е., SETCURRENTKEY все-таки влияет на выбор ключа при выполнении запроса??? Или где я ошибся?

PS: 3.70B, SQL2000.
Старый 09.10.2007, 15:03   #33  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
очень интересно!

Выложите, пожалуйста, SQL Statement для обоих случаев
Старый 09.10.2007, 15:54   #34  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
1) SELECT * FROM "Test$G_L Entry" WITH (READUNCOMMITTED) WHERE (("G_L Account No_"=?)) ORDER BY "Entry No_" OPTION (FAST 5)

2) SELECT * FROM "Test$G_L Entry" WITH (READUNCOMMITTED) WHERE (("G_L Account No_"=?)) ORDER BY "G_L Account No_","Posting Date","Entry No_" OPTION (FAST 5)
Старый 09.10.2007, 16:21   #35  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
Это изза идиотских хинтов FAST в конце запроса (интересна логика разработчиков микрософт, которые их решили использовать).

Попробуйте перестроить индексы и обновить статисику вашей таблицы:

Код:
DBCC DBREINDEX ('[Test$G_L Entry]')
Код:
UPDATE STATISTICS [Test$G_L Entry]
Старый 09.10.2007, 16:32   #36  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Цитата:
Сообщение от golyshev Посмотреть сообщение
Это изза идиотских хинтов FAST в конце запроса (интересна логика разработчиков микрософт, которые их решили использовать).

Попробуйте перестроить индексы и обновить статисику вашей таблицы:

Код:
DBCC DBREINDEX ('[Test$G_L Entry]')
Код:
UPDATE STATISTICS [Test$G_L Entry]
Сделал. Ничего не изменилось.
Старый 09.10.2007, 16:40   #37  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Хотя нет. Сейчас получилось:
SELECT TOP 1 NULL FROM "Test$G_L Entry" WITH (READUNCOMMITTED) WHERE (("G_L Account No_"=?))

SQL Plan = Top[2,1];Index Seek($1)[4,2]
Старый 09.10.2007, 16:58   #38  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
SELECT TOP 1 NULL - это ISEMPTY а не FIND('-')

Вы что-то путаете, по-моему.
Старый 09.10.2007, 17:25   #39  
Cheb is offline
Cheb
Участник
Лучший по профессии 2017
 
138 / 13 (1) ++
Регистрация: 22.09.2002
Адрес: Ростов-на-Дону -> Москва
Нет, точно FIND('-')
Сейчас проверил, получилось:
Source Text = IF GLEntry.FIND('-') THEN;
SQL Statement = SELECT * FROM "Test$G_L Entry" WITH (READUNCOMMITTED) WHERE (("G_L Account No_"=?)) ORDER BY "Entry No_" OPTION (FAST 5)
SQL Plan = Sort[3,1];Bookmark Lookup[4,3];Index Seek($1)[5,4]


Ничего не понимаю, через 5 мин. запустил:

Source Text = IF GLEntry.FIND('-') THEN;
SQL Statement = SELECT * FROM "Test$G_L Entry" WITH (READUNCOMMITTED) WHERE (("G_L Account No_"=?)) ORDER BY "Entry No_" OPTION (FAST 5)
SQL Plan = Clustered Index Scan(Test$G_L Entry$0)[3,1]
Старый 09.10.2007, 17:32   #40  
Голышев Михаил is offline
Голышев Михаил
Участник
 
106 / 10 (1) +
Регистрация: 03.07.2006
Изза хинтов (FAST 5) SQL тупит.
Вы перестроили индексы? Обновили статистику?
 


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 09:50.