1. За да оптимизирате заявката, трябва да се опитате да избегнете пълно сканиране на таблиците и първо да помислите за създаване на индекс върху колоните, участващи в where и подредени по.
2. Опитайте се да избягвате използването на оператори != или <> в клаузата where, в противен случай двигателят ще се откаже от използването на индекси и ще извърши сканиране на цялата таблица.
3. Опитайте се да избегнете нулевата оценка на полетата в клаузата where, в противен случай двигателят ще се откаже от използването на индекси и ще извърши пълно сканиране на таблицата, като:
Изберете id от T, където num е null
Можете да зададете стойността по подразбиране 0 на num, да се уверите, че няма null стойност в колоната num в таблицата, и след това да направите заявка по следния начин:
Изберете id от T, където num=0
4. Трябва да се опитате да избягвате използването на OR в клаузата where за присъединяване към състоянието, в противен случай това ще накара двигателя да се откаже от използването на индекси и да извърши пълно сканиране на таблицата, като:
Изберете ID от T, където num=10 или num=20
Можете да изпращате заявка по следния начин:
Изберете id от T, където num=10
Union All
Изберете id от T, където num=20
5. Следната заявка ще доведе и до пълно сканиране на таблицата:
Изберете id от T, където име като '%abc%'
За да подобрите ефективността, обмислете търсене в пълен текст.
6.in и не е включено също трябва да се използват с внимание, в противен случай това ще доведе до пълно сканиране на масата, като например:
Изберете ID от T, където num in(1,2,3)
За непрекъснати стойности не използвайте in, ако можете да използвате между:
Изберете ID от T, където NUM е между 1 и 3
7. Ако използвате параметър в клауза за where, това ще предизвика и пълно сканиране на таблицата. Тъй като SQL разрешава локални променливи само по време на изпълнение, но оптимизаторът не може да отлага избора на планове за достъп до runtime; Тя трябва да бъде избрана по време на компилацията. Въпреки това, ако план за достъп бъде установен по време на компилация, стойността на променливата остава неизвестна и следователно не може да се използва като входен елемент за избор на индекс. Следните изявления ще бъдат сканирани изцяло:
Изберете id от T, където num=@num
Можете да принудите заявката да използва индекс вместо това:
Изберете id от t с (index(index(index(index name)), където num=@num
8. Опитайте се да избягвате изразяване на полета в клаузата "where", което ще накара двигателя да се откаже от използването на индекси в полза на пълно сканиране на таблицата. Например:
Изберете id от T, където num/2=100
Трябва да се промени на:
Изберете id от T, където num=100*2
9. Опитайте се да избегнете изпълнението на функционални операции върху полета в клаузата where, което ще накара двигателя да се откаже от използването на индекси в полза на пълно сканиране на таблицата. Например:
Изберете id от T, където substring(Name,1,3)='ABC' --Име ID, започващ с ABC
Изберете id от T, където Datediff(Day,Created,'2005-11-30')=0--'2005-11-30' генериран ID
Трябва да се промени на:
Изберете ID от T, където име като 'abc%'
Изберете id от T, където създадено>='2005-11-30' и създадено<'2005-12-1'
10. Не изпълнявайте функции, аритметични операции или други операции с израз вляво от "=" в клаузата "where", в противен случай системата може да не може да използва индекса правилно.
11. Когато се използва индексно поле като условие, ако индексът е съставен, първото поле в индекса трябва да се използва като условие, за да се гарантира, че системата използва индекса, в противен случай индексът няма да се използва, а редът на полетата трябва да е максимално съвместим с реда на индекса.
12. Не пишете някакви безсмислени заявки, като например генериране на празна таблица:
Изберете COL1,COL2 в #t от T, където 1=0
Този тип код не връща никакъв набор от резултати, но консумира системни ресурси, затова трябва да се промени на нещо подобно:
създаване на таблица #t(...)
13. Често е добър избор да се замени с съществуване:
Изберете num от A where num in (изберете num от b)
Заменете със следното изявление:
Изберете num от a където съществува (изберете 1 от b, където num=a.num)
14. Не всички индекси са валидни за заявки, SQL се базира на данните в таблицата, за да оптимизира заявката, когато индексната колона има голямо дублиране на данни, SQL заявките може да не използват индекса, например таблица има пол поле, мъжки, женски са почти половината от всяка, дори ако индексът е изграден върху пола, той няма да играе роля за ефективността на заявките.
15. Колкото повече индекси не са, толкова по-добре, индексът със сигурност може да подобри ефективността на съответния select, но също така намалява ефективността на вмъкване и обновяване, тъй като индексът може да бъде възстановен при вмъкване или актуализация, затова как да се изгради индекс трябва да се обмисли внимателно, в зависимост от конкретната ситуация. Най-добре е да не се има повече от 6 индекса в таблица, а ако са твърде много, да се помисли дали е необходимо да се изграждат индекси върху някои рядко използвани колони.
16. Избягвайте актуализирането на клъстерирани индексни колони колкото е възможно повече, защото редът на клъстерираните индексни колони е физическият ред на съхранение на таблицените записи, а след промяна на стойността на колоната това ще доведе до корекция на реда на всички таблицни записи, което ще изразходва значителни ресурси. Ако вашето приложение трябва често да обновява клъстерирани индексни колони, трябва да обмислите дали да изградите индекса като клъстериран индекс.
17. Опитайте се да използвате числови полета и не проектирайте полета, които съдържат само числова информация като символи, което ще намали производителността на заявките и връзките и ще увеличи натоварването за съхранение. Това е така, защото двигателят сравнява всеки символ в низа един по един при обработка на заявки и съединения, докато при числовите типове е необходимо да се сравни само веднъж.
18. Използвайте varchar/nvarchar вместо char/nchar колкото е възможно повече, защото първо, по-дългото поле за съхранение може да спести пространство, а второ, при заявки ефективността на търсене в сравнително малко поле е очевидно по-висока.
19. Не използвайте select * от t никъде, заменете "*" с конкретен списък с полета и не връщайте полета, които не са използвани.
20. Опитайте да използвате променливи на таблици вместо временни таблици. Ако променливата в таблицата съдържа голямо количество данни, имайте предвид, че индексът е много ограничен (само основният ключов индекс).
21. Избягвайте честото създаване и изтриване на временни таблици, за да намалите потреблението на ресурси на системните таблици.
22. Временните таблици не са неизползваеми и правилната им употреба може да направи някои рутини по-ефективни, например когато трябва многократно да се позовавате на даден набор от данни в голяма или често използвана таблица. Въпреки това, за еднократни събития е най-добре да се използва таблица за експортиране.
23. При създаване на временна таблица, ако количеството данни, вмъкнати наведнъж, е голямо, можете да използвате select in вместо create таблица, за да избегнете увеличаване на скоростта на голям брой логове; Ако обемът на данните не е голям, за да улесниш ресурсите на системната таблица, първо трябва да създадеш таблица и след това да я вмъкнеш.
24. Ако се използва временна таблица, уверете се, че изрично изтривате всички временни таблици в края на съхранената процедура, първо откъсвате таблицата и след това я премахвате, за да избегнете дългосрочното заключване на системната таблица.
25. Опитайте се да избягвате използването на курсора, защото ефективността му е ниска; ако данните, управлявани от курсора, надвишават 10 000 реда, тогава трябва да обмислите пренаписване.
26. Трябва да се търсят решения, базирани на множества, за решаване на проблеми, преди използването на курсорни или временни таблични методи, които често са по-ефективни.
27. Както временните маси, курсорите не са неизползваеми. Използването на FAST_FORWARD курсори за малки набори от данни често е по-добро от другите методи за обработка ред по ред, особено ако трябва да се позовавате на няколко таблици, за да получите нужните данни. Рутините, които включват "total" в набора от резултати, обикновено са по-бързи от тези, които се изпълняват с курсора. Ако времето за разработка позволява, могат да се изпробват както курсорни, така и множествени методи, за да се види кой работи по-добре.
28. Задайте SET NOCOUNT ON в началото на всички съхранени процедури и тригери, и SET NOCOUNT OFF в края. Няма нужда да се изпращат DONE_IN_PROC съобщения на клиента след изпълнение на всяко изявление на съхранената процедура и тригър.
29. Опитайте се да избегнете връщането на големи данни към клиента, ако обемът на данните е твърде голям, преценете дали съответното търсене е разумно.
30. Опитайте се да избегнете големи транзакционни операции и да подобрите възможностите за конкурентност на системата.
|