Защо е необходимо толкова много време за изпълнение на заявка? Защо няма индекси? Вероятно сте чували за EXPLAIN в PostgreSQL. Въпреки това, все още има много хора, които нямат представа как да го използват. Надявам се тази статия да помогне на потребителите да се справят с този страхотен инструмент.
Тази статия е авторска редакция на Understanding EXPLAIN от Гийом Леларж. Тъй като пропуснах някаква информация, горещо ви препоръчвам да се запознаете с оригинала.
Дяволът не е толкова черен, колкото го рисуват
Важно е да се разбере логиката на ядрото на PostgreSQL за оптимизиране на заявките. ще се опитам да обясня. Наистина не е толкова сложно.
EXPLAIN показва необходимата информация, която обяснява какво прави ядрото за всяка конкретна заявка.
Нека да разгледаме какво показва командата EXPLAIN и да разберем какво точно се случва в PostgreSQL. Можете да приложите тази информация към PostgreSQL 9.2 и по-нови версии.
Нашите задачи:
- Научете как да четете и разбирате изхода на командата EXPLAIN
- Разберете какво се случва в PostgreSQL, когато се изпълни заявка
Първи стъпки
Ще тренираме върху тестова маса с милион редове.
CREATE TABLE foo (c1 integer, c2 text); INSERT INTO foo SELECT i, md5(random()::text) FROM generate_series(1, 1000000) AS i;
Опитайте се да прочетете данните
EXPLAIN SELECT * FROM foo;
Възможно е да четете данни от таблица по няколко начина. В нашия случай EXPLAIN уведомява, че се използва Seq Scan — последователно, блок по блок, четене на Foo таблица на данни.
Какво е цена ?
Е, това не е време, а концепция, предназначена да оцени разходите за операция. Първата стойност 0,00 е разходите за получаване на първия ред. Втората стойност 18334,00 е разходите за получаване на всички редове.
Редове са приблизителният брой редове, върнати при извършване на операция Seq Scan. Планировчикът връща тази стойност. В моя случай съвпада с действителния брой редове в таблицата.
Ширина е среден размер на един ред в байтове.
Нека се опитаме да добавим 10 реда.
INSERT INTO foo SELECT i, md5(random()::text) FROM generate_series(1, 10) AS i; EXPLAIN SELECT * FROM foo;
Стойността на редовете не е променена. Статистиката на таблицата е стара. За да актуализирате статистиката, извикайте командата ANALYZE.
Сега, редове показва правилния брой редове.
Какво се случва при изпълнение на ANALYZE?
- Случайно се избират и четат определен брой редове от таблицата.
- Статистика на стойностите по всяка колона се събира.
Броят на четените от ANALYZE редове зависи от параметъра default_statistics_target.
Действителни данни
Всичко, което видяхме по-горе в изхода на командата EXPLAIN, е това, което планиращият очаква да получи. Нека се опитаме да ги сравним с резултатите от действителните данни. За да направите това, използвайте EXPLAIN (АНАЛИЗ).
EXPLAIN (ANALYZE) SELECT * FROM foo;
Такава заявка наистина ще бъде изпълнена. Така че, ако изпълните EXPLAIN (ANALYZE) за операторите INSERT, DELETE или UPDATE, вашите данни ще бъдат променени. Бъди внимателен! В тези случаи използвайте командата ROLLBACK.
Командата показва следните допълнителни параметри:
- действителното време е действителното време в милисекунди, изразходвано за получаване на първия ред и съответно на всички редове.
- редове е действителният брой редове, получени с Seq Scan.
- цикли е броят пъти, когато е трябвало да се извърши операцията Seq Scan.
- Общото време на изпълнение е общото време на изпълнение на заявката.
Допълнително четене:
Оптимизация на заявки в PostgreSQL. EXPLAIN Basics – Част 2
Оптимизация на заявки в PostgreSQL. EXPLAIN Basics – Част 3