|
![]() |
#1 |
Участник
|
Цитата:
При нормальных ключах и статистике ключ выбирается правильно, даже если не указан setcurrentkey, т.е. только с условием where.
Цитата:
Сообщение от ;362029
Можно привести массу примеров, где это утверждение не верно.
|
|
![]() |
#2 |
Участник
|
Цитата:
Цитата:
Сообщение от smoyk
![]() Естественно, но так как мы сортируем именно по полям, по которым проводим поиск, то никакие другие примеры здесь не уместны Вызывая SETCURRENTKEY мы не только сортируем (что значительно ускоряет поиск), но и явно указываем выбираемый ключ. Если SQL 2005 выберет другой ключ исходя из своей логики, думаю это будет не правильно. Думаю, он этого и не сделает имхо. Или я не прав и Вы можете такие примеры привести?
|
|
![]() |
#3 |
Участник
|
Цитата:
Сообщение от MSI
![]() И для каждого из таких запросов, как я понял, надо приципить свой план. Геморройно... Или надо что-то не так делать? Может мы не так лечим и надо действительно сделать обновление статистики и сиквель должен начать правильно выстраивать планы выполнения? Или можно как-то назначить план на группу запросов?
К сожалению, обновление статистики сможет починить лишь запросы, которые идут из кода. (Тем не менее обновлять статистику нужно обязательно. По особо большим и популярным таблицам - каждую ночь) При открытии же форм, как раз идут запросы с > >= < и <=. Например при фильтрации финансовых операций по счету будет запрос: Код: exec sp_executesql N'SELECT * FROM "dbo"."КРОК$G_L_Entry" WHERE (("G_L_Account_No_"=@P1)) AND "Entry_No_">=@P2 ORDER BY "Entry_No_" OPTION (FAST 10)', N'@P1 varchar(20),@P2 int','61100100',4 Очевидно, что если в качестве @P2 первый раз было передано большое число, то план будет построен по кластерному индексу. (Если @P2 маленькое, то план будет правильный - состоять из джоина Index Seek по G_L_Account и Clustered Index Seek) И в дальнейшем, этот план по кластерному индексу будет использован и для маленьких @P2, что будет приводить к сканированию всей таблицы. Эти случаи надо фиксить Plan Guide'ами |
|
![]() |
#4 |
Участник
|
Цитата:
Во первых набор данных будет упорядочен по первичному ключу. В вторых, поиск будет идти быстрее, поскольку при использовании не кластерного индекса, к нему всегда идет join кластерного, в котором данные как раз УЖЕ упорядочены по первичному ключу. Цитата:
Это дополнительное действие, которое либо является отдельным пунктом плана запроса, либо входит в этап джоина таблиц. Пример будет вечером. Специально сделаю его на CRONUS, чтобы Вам удалось его повторить. |
|
![]() |
#5 |
Участник
|
CRONUS Россия ЗАО (navision sp3) на ms sql 2005
Типичный пример на 17 таблице. Прежде всего, заполняем фин книгу (300 записей - это не серьезно) Код: Name DataType Subtype Length i Integer dlg Dialog recGenJnlTEMP Record Gen. Journal Line recGenJnlDimTEMP Record Journal Line Dimension Gen. Jnl.-Post Line Codeunit Gen. Jnl.-Post Line --------- dlg.OPEN('@1##################'); FOR i := 1 TO 1000000 DO BEGIN dlg.UPDATE(1,i DIV 100); recGenJnlTEMP.DELETEALL; recGenJnlTEMP.INIT; recGenJnlTEMP.VALIDATE("Posting Date" , 010105D); recGenJnlTEMP.VALIDATE("Account Type" , recGenJnlTEMP."Account Type"::Customer); recGenJnlTEMP.VALIDATE("Account No." , '49633663'); recGenJnlTEMP.VALIDATE("Document No." , 'INITIAL'); recGenJnlTEMP.VALIDATE(Description , 'Автозапонение'); recGenJnlTEMP.VALIDATE(Amount,100); recGenJnlTEMP.VALIDATE("Bal. Account Type",recGenJnlTEMP."Bal. Account Type"::"G/L Account"); recGenJnlTEMP.VALIDATE("Bal. Account No.",'68-800'); recGenJnlTEMP.VALIDATE("Shortcut Dimension 1 Code",'ПРОДАЖИ'); recGenJnlTEMP.VALIDATE("Shortcut Dimension 2 Code",'МЕРСЕДЕС'); recGenJnlTEMP.INSERT; recGenJnlDimTEMP.DELETEALL; recGenJnlDimTEMP.INIT; recGenJnlDimTEMP."Table ID" := 81; recGenJnlDimTEMP."Dimension Code" := 'ПРОДМЕНЕД'; recGenJnlDimTEMP."Dimension Value Code" := 'ВК'; recGenJnlDimTEMP.INSERT; "Gen. Jnl.-Post Line".RunWithCheck(recGenJnlTEMP,recGenJnlDimTEMP); COMMIT; END; Код: recGLEntry.RESET; recGLEntry.SETCURRENTKEY("Source Type","Source No."); recGLEntry.SETRANGE("Source Type",recGLEntry."Source Type"::Customer); recGLEntry.SETRANGE("Source No.",'49633663'); recGLEntry.SETRANGE("Document No.",'104005'); recGLEntry.FIND('-'); Код: exec sp_executesql N'SELECT * FROM "CRONUS"."dbo"."CRONUS Россия ЗАО$G_L Entry" WITH (READUNCOMMITTED) WHERE (("Source Type"=@P1)) AND (("Source No_"=@P2)) AND (("Document No_"=@P3)) ORDER BY "Source Type","Source No_","G_L Account No_","Global Dimension 1 Code","Global Dimension 2 Code","Business Unit Code","Posting Date","Entry No_" OPTION (FAST 5)', N'@P1 int,@P2 varchar(20),@P3 varchar(20)' ,1,'49633663','104005' ![]() |
|