Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Ефикасен начин за получаване на @@rowcount от заявка с помощта на row_number

През годините купчина пот на разработчиците е отишла за ефективно пейджинг набори от резултати. И все пак няма един отговор - зависи от вашия случай на употреба. Част от случая на използване е да получите страницата си ефективно, част е да разберете колко реда има в пълен набор от резултати. Така че съжалявам, ако се отклонявам малко от страниците, но двете са доста тясно свързани в съзнанието ми.

Има много стратегии, повечето от които са лоши, ако имате някакъв обем данни и не отговаряте на случая на употреба. Въпреки че това не е пълен списък, следват някои от опциите.....

Изпълнете отделно Count(*)

  • изпълнете отделна заявка, която прави просто „изберете брой(*) от MyTable“
  • просто и лесно за малка маса
  • добре за нефилтрирана голяма таблица, която е или тясна, или има компактен негрупиран индекс, който можете да използвате
  • се разваля, когато имате сложен WHERE/JOIN критерии, защото изпълнява WHERE/JOIN два пъти е скъпо.
  • се разбива на широк индекс, защото броят на прочитанията нараства.

Комбинирайте ROW_Number() OVER() и COUNT(1) OVER(PARTITION By 1)

  • Това беше предложено от @RBarryYoung. Предимството му е, че е лесен за изпълнение и много гъвкав.
  • Недостатъкът е, че има много причини това бързо да стане изключително скъпо.
  • Например, в база данни, с която работя в момента, има медийна таблица с около 6000 реда. Не е особено широк, има целочислен клъстерен PK и, както и компактен уникален индекс. И все пак, прост COUNT(*) OVER(PARTITION BY 1) as TotalRows води до ~12 000 прочитания. Сравнете това с прост SELECT COUNT(*) FROM Media -- 12 прочитания. Удивителни.

Временни таблици/променливи на таблици

  • Има много стратегии, които вземат набор от резултати и вмъкват подходящи ключове или сегменти от резултати във временни таблици/променливи на таблици.
  • За малки/средни набори от резултати това може да осигури страхотни резултати.
  • Този тип стратегия работи в почти всяка платформа/версия на SQL.
  • Многократното опериране с набор от резултати (доста често изискване) също е лесно.
  • Недостатъкът е, че когато работите с големи набори от резултати... вмъкването на няколко милиона реда във временна таблица има цена.
  • Проблемът се усложнява, тъй като в система с голям обем натискът върху TempDB може да бъде доста важен фактор и временните таблици работят ефективно в TempDB.

Сума на Гаус / Число с двоен ред

  • Тази идея разчита на подмножество на нещо, което математикът Гаус измисли (как да се сумира поредица от числа). Подмножеството е как да получите броя на редовете от всяка точка в таблицата.
  • От поредица от числа (Row_Number() ) броят на редовете за 1 до N е (N + 1) - 1 . Повече обяснения в линковете.
  • Формулата изглежда така, сякаш ще достигне само N, но ако се придържате към формулата, се случват интересни неща, можете да разберете броя на редовете от страница в средата на таблицата.
  • Нетният резултат е, че правите ROW_Number() OVER(Order by ID) и ROW_Number() OVER(Order by ID DESC) след това сумирайте двете числа и извадете 1.
  • Използвайки моята медийна таблица като пример, моите четения спаднаха от 12 000 на около 75.
  • В по-голяма страница в крайна сметка сте повтаряли данни много пъти, но отместването при четенията може да си заслужава.
  • Не съм тествал това в твърде много сценарии, така че може да се разпадне в други сценарии.

Най-горе (@n) / ЗАДАДЕ БРОЙ РЕДОВ

  • Това не са конкретни стратегии сами по себе си, а са оптимизации въз основа на това, което знаем за оптимизатора на заявки.
  • Креативното използване на Top(@n) [top може да бъде променлива в SQL 2008] или SET ROWCOUNT може да намали работния ви набор ... дори ако изтегляте средна страница от набор с резултати, пак можете да стесните резултата
  • Тези идеи работят поради поведението на оптимизатора на заявки ... сервизен пакет/актуална корекция може да промени поведението (въпреки че вероятно не).
  • В някои случаи SET ROWCOUNT може да е малко по-точен
  • Тази стратегия не отчита получаването на пълния брой редове, а само прави странирането по-ефективно

И така, какво трябва да прави разработчикът?

Чети добри човече, чети. Ето няколко статии, на които се опрях...

Надявам се, че това помага.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да получите първата и последната дата на текущата година?

  2. Изпробвайте тези най-добри практики за наблюдение на база данни на MySQL

  3. вземете нов идентификатор на SQL запис

  4. Запазване на връзките родител-дете при копиране на йерархични данни

  5. свържете sql сървър 2005/2008 през интернет