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

Заявката за избор с ограничение за отместване е твърде бавна

Той е бавен, защото трябва да намери горния offset редове и сканирайте следващите 100. Никаква оптимизация няма да промени това, когато имате работа с огромни отмествания.

Това е така, защото вашата заявка буквално инструктира DB машината да посещава много редове с помощта на offset 3900000 -- това са 3,9 милиона реда. Опциите за ускоряване на това донякъде не са много.

Супер бързата RAM, SSD дисковете и т.н. ще помогнат. Но вие ще спечелите само от постоянен фактор, което означава, че просто ритате кутията надолу по пътя, докато достигнете достатъчно по-голямо изместване.

Да се ​​уверите, че таблицата се вписва в паметта, с много повече резерви, също ще помогне с по-голям постоянен коефициент - с изключение на първия път. Но това може да не е възможно с достатъчно голяма таблица или индекс.

Да се ​​уверите, че правите сканиране само за индекс, ще работи до известна степен. (Вижте отговора на velis; той има много предимства.) Проблемът тук е, че за всички практически цели можете да мислите за индекс като таблица, съхраняваща местоположение на диска и индексираните полета. (По-оптимизиран е от това, но е разумно първо приближение.) При достатъчно редове все още ще срещате проблеми с достатъчно по-голямо отместване.

Опитът за съхраняване и поддържане на точната позиция на редовете също е скъп подход. (Това е предложено от например benjist.) Макар че е технически осъществимо, той страда от ограничения, подобни на тези, които произтичат от използването на MPTT с дървовидна структура:ще спечелите значително при четене, но в крайна сметка ще получите прекомерно време за запис, когато възел бъде вмъкнат, актуализиран или премахнат по такъв начин, че големи парчета данни трябва да бъдат актуализирани заедно.

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

Ако пагинирате въз основа на идентификатора (или поле за дата, или друг набор от полета, който може да се индексира), потенциален трик (използван от blogspot, например) би бил да накарате вашата заявка да започне от произволна точка в индекса.

Казано по друг начин, вместо:

example.com?page_number=[huge]

Направете нещо като:

example.com?page_following=[huge]

По този начин запазвате следа за това къде се намирате във вашия индекс и заявката става много бърза, защото може да се насочи направо към правилната начална точка, без да преминава през газилион редове:

select * from foo where ID > [huge] order by ID limit 100

Естествено губите способността да скачате до напр. страница 3000. Но помислете честно:кога за последен път прескочихте до огромен номер на страница в даден сайт, вместо да отидете направо към месечните му архиви или да използвате полето за търсене?

Ако пагинирате, но искате да запазите изместването на страницата по някакъв начин, друг подход е да забраните използването на по-голям номер на страница. Не е глупаво:това прави Google с резултатите от търсенето. Когато изпълнявате заявка за търсене, Google ви дава приблизителен брой резултати (можете да получите разумен брой, като използвате explain ), и след това ще ви позволи да разгледате първите няколко хиляди резултата - нищо повече. Наред с други неща, те го правят и от съображения за производителност – точно тази, с която се сблъсквате.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. postgresql - замества всички екземпляри на низ в текстовото поле

  2. PostgreSQL - Добавете ключ към всеки обект от JSONB масив

  3. PostgreSQL Upsert разграничава вмъкнатите и актуализираните редове с помощта на системни колони XMIN, XMAX и други

  4. ГРЕШКА в PostgreSQL:функция to_tsvector(променлив знак, неизвестен) не съществува

  5. INSERT IN... FROM SELECT ... ВРЪЩАНЕ на идентификационните съпоставяния