เบ„เปเบฒเบ–เบฒเบกเบ‚เบฐเบซเบ™เบฒเบ™เปƒเบ™ PostgreSQL

เบ„เปเบฒเบ–เบฒเบกเบ‚เบฐเบซเบ™เบฒเบ™เปƒเบ™ PostgreSQL
CPU เบ—เบตเปˆเบ—เบฑเบ™เบชเบฐเป„เบซเบกเบกเบตเปเบเบ™เบซเบผเบฒเบ. เบชเปเบฒเบฅเบฑเบšเบ›เบต, เบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบเป„เบ”เป‰เบชเบปเปˆเบ‡เบ„เปเบฒเบ–เบฒเบกเป„เบ›เบซเบฒเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปƒเบ™เบ‚เบฐเบซเบ™เบฒเบ™. เบ–เป‰เบฒเบกเบฑเบ™เป€เบ›เบฑเบ™เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบฅเบฒเบเบ‡เบฒเบ™เบขเบนเปˆเปƒเบ™เบซเบผเบฒเบเปเบ–เบงเปƒเบ™เบ•เบฒเบ•เบฐเบฅเบฒเบ‡, เบกเบฑเบ™เป€เบฎเบฑเบ”เบงเบฝเบเป„เบงเบ‚เบถเป‰เบ™เป€เบกเบทเปˆเบญเปƒเบŠเป‰ CPU เบซเบผเบฒเบ, เปเบฅเบฐ PostgreSQL เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เป„เบ”เป‰เบ•เบฑเป‰เบ‡เปเบ•เปˆเบฎเบธเปˆเบ™ 9.6.

เบกเบฑเบ™เปƒเบŠเป‰เป€เบงเบฅเบฒ 3 เบ›เบตเป€เบžเบทเปˆเบญเบ›เบฐเบ•เบดเบšเบฑเบ”เบ„เบธเบ™เบชเบปเบกเบšเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ‚เบฐเบซเบ™เบฒเบ™ - เบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบ‚เบฝเบ™เบฅเบฐเบซเบฑเบ”เบ„เบทเบ™เปƒเบซเบกเปˆเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ•เปˆเบฒเบ‡เป†เบ‚เบญเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบก. PostgreSQL 9.6 เป„เบ”เป‰เบ™เปเบฒเบชเบฐเป€เบซเบ™เบตเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบžเบทเป‰เบ™เบ–เบฒเบ™เป€เบžเบทเปˆเบญเบ›เบฑเบšเบ›เบธเบ‡เบฅเบฐเบซเบฑเบ”เบ•เบทเปˆเบกเบญเบตเบ. เปƒเบ™เบชเบฐเบšเบฑเบšเบ•เปเปˆเบกเบฒ, เบ›เบฐเป€เบžเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบญเบทเปˆเบ™เป†เปเบกเปˆเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™.

Restrictions

  • เบขเปˆเบฒเป€เบ›เบตเบ”เปƒเบŠเป‰เบ‡เบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™เบ–เป‰เบฒเปเบเบ™เบ—เบฑเบ‡เปเบปเบ”เบšเปเปˆเบซเบงเปˆเบฒเบ‡เปเบฅเป‰เบง, เบ–เป‰เบฒเบšเปเปˆเบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเบญเบทเปˆเบ™เป†เบˆเบฐเบŠเป‰เบฒเบฅเบปเบ‡.
  • เบชเบดเปˆเบ‡เบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™เบ—เบตเปˆเบชเบธเบ”, เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบฐเบซเบ™เบฒเบ™เบ—เบตเปˆเบกเบตเบ„เปˆเบฒ WORK_MEM เบชเบนเบ‡เปƒเบŠเป‰เบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒเบซเบผเบฒเบ - เปเบ•เปˆเบฅเบฐ hash เป€เบ‚เบปเป‰เบฒเบฎเปˆเบงเบกเบซเบผเบทเบเบฒเบ™เบˆเบฑเบ”เบฅเบฝเบ‡เปƒเบŠเป‰เป€เบงเบฅเบฒเป€เบ–เบดเบ‡เบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒ work_mem.
  • เบเบฒเบ™เบชเบญเบšเบ–เบฒเบก OLTP เบ—เบตเปˆเบกเบตเป€เบงเบฅเบฒเบ•เบญเบšเบชเบฐเปœเบญเบ‡เบ•เปเปˆเบฒเบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบฅเบฑเปˆเบ‡เป„เบ”เป‰เป‚เบ”เบเบเบฒเบ™เบ”เบณเป€เบ™เบตเบ™เบเบฒเบ™เบ‚เบฐเปœเบฒเบ™. เปเบฅเบฐเบ–เป‰เบฒเบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบชเบปเปˆเบ‡เบ„เบทเบ™เบซเบ™เบถเปˆเบ‡เปเบ–เบง, เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบฐเบซเบ™เบฒเบ™เบˆเบฐเบŠเป‰เบฒเบฅเบปเบ‡เป€เบ—เบปเปˆเบฒเบ™เบฑเป‰เบ™.
  • เบ™เบฑเบเบžเบฑเบ”เบ—เบฐเบ™เบฒเบกเบฑเบเปƒเบŠเป‰ TPC-H benchmark. เบšเบฒเบ‡เบ—เบตเป€เบˆเบปเป‰เบฒเบกเบตเบ„เปเบฒเบ–เบฒเบกเบ—เบตเปˆเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบฐเบซเบ™เบฒเบ™เบ—เบตเปˆเบชเบปเบกเบšเบนเบ™เปเบšเบš.
  • เบžเบฝเบ‡เปเบ•เปˆ SELECT queries เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™ locking predicate เป„เบ”เป‰เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เบ‚เบฐเบซเบ™เบฒเบ™.
  • เบšเบฒเบ‡เบ„เบฑเป‰เบ‡เบเบฒเบ™เบ”เบฑเบ”เบชเบฐเบ™เบตเบ—เบตเปˆเป€เบซเบกเบฒเบฐเบชเบปเบกเปเบกเปˆเบ™เบ”เบตเบเปˆเบงเบฒเบเบฒเบ™เบชเบฐเปเบเบ™เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ•เบฒเบกเบฅเปเบฒเบ”เบฑเบšเปƒเบ™เบฎเบนเบšเปเบšเบšเบ‚เบฐเบซเบ™เบฒเบ™.
  • เบšเปเปˆเบฎเบญเบ‡เบฎเบฑเบšเบเบฒเบ™เบขเบธเบ”เบ„เบดเบงเบฃเบต เปเบฅเบฐเป€เบ„เบตเป€เบŠเบต.
  • เบŸเบฑเบ‡เบŠเบฑเบ™เปœเป‰เบฒเบ•เปˆเบฒเบ‡ เปเบฅเบฐเบŸเบฑเบ‡เบŠเบฑเบ™เบฅเบงเบกเบ—เบตเปˆเบ•เบฑเป‰เบ‡เบ•เบฒเบกเบฅเบณเบ”เบฑเบšเปเบกเปˆเบ™เบšเปเปˆเบ‚เบฐเปœเบฒเบ™เบเบฑเบ™.
  • เป€เบˆเบปเป‰เบฒเบšเปเปˆเป„เบ”เป‰เบฎเบฑเบšเบซเบเบฑเบ‡เปƒเบ™ I/O workload.
  • เบšเปเปˆเบกเบตเบฅเบฐเบšเบปเบšเบเบฒเบ™เบˆเบฑเบ”เบฎเบฝเบ‡เปเบšเบšเบ‚เบฐเปœเบฒเบ™. เปเบ•เปˆเบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ—เบตเปˆเบกเบตเบเบฒเบ™เบˆเบฑเบ”เบฅเบฝเบ‡เบชเบฒเบกเบฒเบ”เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เบ‚เบฐเบซเบ™เบฒเบ™เปƒเบ™เบšเบฒเบ‡เบ”เป‰เบฒเบ™.
  • เปเบ—เบ™เบ—เบตเปˆ CTE (เบ”เป‰เบงเบ ...) เบ”เป‰เบงเบ SELECT เบŠเป‰เบญเบ™เบเบฑเบ™เป€เบžเบทเปˆเบญเป€เบ›เบตเบ”เปƒเบŠเป‰เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเปœเบฒเบ™.
  • เบ•เบปเบงเบซเปเปˆเบ‚เปเป‰เบกเบนเบ™เบ‚เบญเบ‡เบžเบฒเบเบชเปˆเบงเบ™เบ—เบตเบชเบฒเบกเบเบฑเบ‡เบšเปเปˆเบฎเบญเบ‡เบฎเบฑเบšเบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเปœเบฒเบ™เป€เบ—เบทเปˆเบญ (เปเบ•เปˆเป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เป„เบ”เป‰!)
  • เบšเปเปˆเบฎเบญเบ‡เบฎเบฑเบšเบเบฒเบ™เป€เบ‚เบปเป‰เบฒเบฎเปˆเบงเบกเป€เบ•เบฑเบกเบฎเบนเบšเปเบšเบš.
  • max_rows เบ›เบดเบ”เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเปœเบฒเบ™.
  • เบ–เป‰เบฒเบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบกเบตเบŸเบฑเบ‡เบŠเบฑเบ™เบ—เบตเปˆเบšเปเปˆเป„เบ”เป‰เบ–เบทเบเปเบฒเบเบงเปˆเบฒ PARALLEL SAFE, เบกเบฑเบ™เบˆเบฐเป€เบ›เบฑเบ™ threaded เบ”เบฝเบง.
  • เบฅเบฐเบ”เบฑเบšเบเบฒเบ™เปเบเบเบ—เบธเบฅเบฐเบเบณ SERIALIZABLE เบ›เบดเบ”เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเปœเบฒเบ™.

เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบเบฒเบ™เบ—เบปเบ”เบชเบญเบš

เบ™เบฑเบเบžเบฑเบ”เบ—เบฐเบ™เบฒ PostgreSQL เบžเบฐเบเบฒเบเบฒเบกเบซเบผเบธเบ”เบœเปˆเบญเบ™เป€เบงเบฅเบฒเบ•เบญเบšเป‚เบ•เป‰เบ‚เบญเบ‡ TPC-H benchmark queries. เบ”เบฒเบงโ€‹เบ™โ€‹เปŒโ€‹เป‚เบซเบฅเบ”โ€‹เบกเบฒเบ”โ€‹เบ•เบฐโ€‹เบ–เบฒเบ™โ€‹เปเบฅเบฐโ€‹ เบ›เบฑเบšเบกเบฑเบ™เป€เบ‚เบปเป‰เบฒเบเบฑเบš PostgreSQL. เบ™เบตเป‰เปเบกเปˆเบ™เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบ—เบตเปˆเบšเปเปˆเป€เบ›เบฑเบ™เบ—เบฒเบ‡เบเบฒเบ™เบ‚เบญเบ‡ TPC-H benchmark - เบšเปเปˆเปเบกเปˆเบ™เบชเปเบฒเบฅเบฑเบšเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบซเบผเบทเบเบฒเบ™เบ›เบฝเบšเบ—เบฝเบšเบฎเบฒเบ”เปเบง.

  1. เบ”เบฒเบงเป‚เบซเบผเบ” TPC-H_Tools_v2.17.3.zip (เบซเบผเบทเป€เบงเบตเบŠเบฑเบ™เปƒเปเปˆเบเบงเปˆเบฒ) เบˆเบฒเบ TPC เบ™เบญเบเบชเบฐเบ–เบฒเบ™เบ—เบตเปˆ.
  2. เบ›เปˆเบฝเบ™เบŠเบทเปˆ makefile.suite เป€เบ›เบฑเบ™ Makefile เปเบฅเบฐเบ›เปˆเบฝเบ™เบ•เบฒเบกเบ—เบตเปˆเบญเบฐเบ—เบดเบšเบฒเบเป„เบงเป‰เบ™เบตเป‰: https://github.com/tvondra/pg_tpch . เบฅเบงเบšเบฅเบงเบกเบฅเบฐเบซเบฑเบ”เบ”เป‰เบงเบเบ„เปเบฒเบชเบฑเปˆเบ‡ make.
  3. เบชเป‰เบฒเบ‡เบ‚เปเป‰เบกเบนเบ™: ./dbgen -s 10 เบชเป‰เบฒเบ‡เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™ 23 GB. เบ™เบตเป‰เปเบกเปˆเบ™เบžเบฝเบ‡เบžเปเบ—เบตเปˆเบˆเบฐเป€เบซเบฑเบ™เบ„เบงเบฒเบกเปเบ•เบเบ•เปˆเบฒเบ‡เปƒเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเปเบšเบšเบ‚เบฐเบซเบ™เบฒเบ™เปเบฅเบฐเบšเปเปˆเบ‚เบฐเบซเบ™เบฒเบ™.
  4. เปเบ›เบ‡เป„เบŸเบฅเปŒ tbl ะฒ csv ั for ะธ sed.
  5. Clone the repository pg_tpch เปเบฅเบฐเบ„เบฑเบ”เบฅเบญเบเป„เบŸเบฅเปŒ csv ะฒ pg_tpch/dss/data.
  6. เบชเป‰เบฒเบ‡เบ„เปเบฒเบ–เบฒเบกเบ”เป‰เบงเบเบ„เปเบฒเบชเบฑเปˆเบ‡ qgen.
  7. เป‚เบซเบฅเบ”เบ‚เปเป‰เบกเบนเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ”เป‰เบงเบเบ„เปเบฒเบชเบฑเปˆเบ‡ ./tpch.sh.

เบเบฒเบ™เบชเบฐเปเบเบ™เบ•เบฒเบกเบฅเปเบฒเบ”เบฑเบšเบ‚เบฐเบซเบ™เบฒเบ™

เบกเบฑเบ™เบญเบฒเบ”เบˆเบฐเป„เบงเบเบงเปˆเบฒเบšเปเปˆเปเบกเปˆเบ™เบเป‰เบญเบ™เบเบฒเบ™เบญเปˆเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™, เปเบ•เปˆเป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบ‚เปเป‰เบกเบนเบ™เบ–เบทเบเปเบœเปˆเบ‚เบฐเบซเบเบฒเบเป„เบ›เบ—เบปเปˆเบง CPU เบซเบผเบฒเบเปเบเบ™. เปƒเบ™เบฅเบฐเบšเบปเบšเบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบ—เบตเปˆเบ—เบฑเบ™เบชเบฐเป„เบซเบก, เป„เบŸเบฅเปŒเบ‚เปเป‰เบกเบนเบ™ PostgreSQL เบ–เบทเบเป€เบเบฑเบšเป„เบงเป‰เบ”เบต. เบ”เป‰เบงเบเบเบฒเบ™เบญเปˆเบฒเบ™เบฅเปˆเบงเบ‡เบซเบ™เป‰เบฒ, เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเป„เบ”เป‰เบฎเบฑเบšเบšเบฅเบฑเบญเบเบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆเบˆเบฒเบเบเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒเบซเบผเบฒเบเบเปˆเบงเบฒเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป PG daemon. เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเปเบกเปˆเบ™เบšเปเปˆเบˆเปเบฒเบเบฑเบ”เป‚เบ”เบ disk I/O. เบกเบฑเบ™เบšเปเบฅเบดเป‚เบžเบเบฎเบญเบšเบงเบฝเบ™ CPU เป€เบžเบทเปˆเบญ:

  • เบญเปˆเบฒเบ™เปเบ–เบงเปœเบถเปˆเบ‡เบ•เปเปˆเบ„เบฑเป‰เบ‡เบˆเบฒเบเปœเป‰เบฒเบ•เบฒเบ•เบฐเบฅเบฒเบ‡;
  • เบ›เบฝเบšเบ—เบฝเบšเบ„เปˆเบฒ string เปเบฅเบฐเป€เบ‡เบทเปˆเบญเบ™เป„เบ‚ WHERE.

เปƒเบซเป‰เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบ select:

tpch=# explain analyze select l_quantity as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Seq Scan on lineitem (cost=0.00..1964772.00 rows=58856235 width=5) (actual time=0.014..16951.669 rows=58839715 loops=1)
Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 1146337
Planning Time: 0.203 ms
Execution Time: 19035.100 ms

เบเบฒเบ™เบชเบฐเปเบเบ™เบ•เบฒเบกเบฅเปเบฒเบ”เบฑเบšเบœเบฐเบฅเบดเบ”เปเบ–เบงเบซเบผเบฒเบเป€เบเบตเบ™เป„เบ›เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบฅเบงเบšเบฅเบงเบก, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเป„เบ”เป‰เบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เป‚เบ”เบ CPU core เบ”เบฝเบง.

เบ–เป‰เบฒเบ—เปˆเบฒเบ™เป€เบžเบตเปˆเบก SUM(), เบ—เปˆเบฒเบ™โ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เป€เบšเบดเปˆเบ‡โ€‹เบงเปˆเบฒโ€‹เบชเบญเบ‡ workflows เบˆเบฐโ€‹เบŠเปˆเบงเบโ€‹เป€เบฅเบฑเปˆเบ‡โ€‹เบเบฒเบ™โ€‹เบชเบญเบšโ€‹เบ–เบฒเบกโ€‹:

explain analyze select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------
Finalize Aggregate (cost=1589702.14..1589702.15 rows=1 width=32) (actual time=8553.365..8553.365 rows=1 loops=1)
-> Gather (cost=1589701.91..1589702.12 rows=2 width=32) (actual time=8553.241..8555.067 rows=3 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (actual time=8547.546..8547.546 rows=1 loops=3)
-> Parallel Seq Scan on lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (actual time=0.038..5998.417 rows=19613238 loops=3)
Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 382112
Planning Time: 0.241 ms
Execution Time: 8555.131 ms

เบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเบ‚เบฐเบซเบ™เบฒเบ™

Parallel Seq Scan node เบœเบฐเบฅเบดเบ”เปเบ–เบงเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเบšเบฒเบ‡เบชเปˆเบงเบ™. เป‚เบ™เบ” "เบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเบšเบฒเบ‡เบชเปˆเบงเบ™" เบ•เบฑเบ”เป€เบชเบฑเป‰เบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เป‚เบ”เบเปƒเบŠเป‰ SUM(). เปƒเบ™เบ—เบตเปˆเบชเบธเบ”, เบ•เบปเบงเบ™เบฑเบš SUM เบˆเบฒเบเปเบ•เปˆเบฅเบฐเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เปเบกเปˆเบ™เป€เบเบฑเบšเบเปเบฒเป‚เบ”เบ node "Gather".

เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบชเบธเบ”เบ—เป‰เบฒเบเปเบกเปˆเบ™เบ„เบดเบ”เป„เบฅเปˆเป‚เบ”เบ "เบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเบชเบธเบ”เบ—เป‰เบฒเบ" node. เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบกเบตเบซเบ™เป‰เบฒเบ—เบตเปˆเบฅเบงเบกเบ‚เบญเบ‡เบ—เปˆเบฒเบ™เป€เบญเบ‡, เบขเปˆเบฒเบฅเบทเบกเบซเบกเบฒเบเบžเบงเบเบกเบฑเบ™เป€เบ›เบฑเบ™ "เบ„เบงเบฒเบกเบ›เบญเบ”เป„เบžเบ‚เบฐเบซเบ™เบฒเบ™".

เบˆเปเบฒเบ™เบงเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™

เบˆเปเบฒเบ™เบงเบ™เบ‚เบญเบ‡เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™ restart server:

explain analyze select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------
Finalize Aggregate (cost=1589702.14..1589702.15 rows=1 width=32) (actual time=8553.365..8553.365 rows=1 loops=1)
-> Gather (cost=1589701.91..1589702.12 rows=2 width=32) (actual time=8553.241..8555.067 rows=3 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (actual time=8547.546..8547.546 rows=1 loops=3)
-> Parallel Seq Scan on lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (actual time=0.038..5998.417 rows=19613238 loops=3)
Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 382112
Planning Time: 0.241 ms
Execution Time: 8555.131 ms

เป€เบเบตเบ”เบซเบเบฑเบ‡เบ‚เบถเป‰เบ™เบขเบนเปˆเบ™เบตเป‰? เบกเบตเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบซเบผเบฒเบเบเบงเปˆเบฒ 2 เป€เบ—เบปเปˆเบฒ, เปเบฅเบฐเบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเป„เบ”เป‰เบเบฒเบเป€เบ›เบฑเบ™เบžเบฝเบ‡เปเบ•เปˆ 1,6599 เป€เบ—เบทเปˆเบญเป„เบง. เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเปเบกเปˆเบ™เบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆ. เบžเบงเบเป€เบฎเบปเบฒเบกเบตเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™ 2 เบ„เบปเบ™ เปเบฅเบฐ เบœเบนเป‰เบ™เปเบฒ 1 เบ„เบปเบ™. เบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบกเบฑเบ™เบเบฒเบเป€เบ›เบฑเบ™ 4+1.

เบ„เบงเบฒเบกเป„เบงเบชเบนเบ‡เบชเบธเบ”เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเบˆเบฒเบเบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเบซเบ™เบฒเบ™: 5/3 = 1,66(6) เบ„เบฑเป‰เบ‡.

เบกเบฑเบ™เบšเปเปˆเป„เบ”เป‰เปเบ™เบงเปƒเบ”เป€เบฎเบฑเบ”เบงเบฝเบ?

เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ•เปˆเบฒเบ‡เป†

เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ”เป‰เบงเบเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ™เปเบฒเบžเบฒเบชเบฐเป€เบซเบกเบต. เบœเบนเป‰เบ™เปเบฒเป€เบฎเบฑเบ”เบ—เบธเบเบชเบดเปˆเบ‡เบ—เบธเบเบขเปˆเบฒเบ‡เบ—เบตเปˆเบšเปเปˆเปเบกเปˆเบ™เบ‚เบฐเบซเบ™เบฒเบ™เปเบฅเบฐเบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบฐเบซเบ™เบฒเบ™เบšเบฒเบ‡. เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบญเบทเปˆเบ™เป†เบ—เบตเปˆเบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเบ”เบฝเบงเบเบฑเบ™เป€เบญเบตเป‰เบ™เบงเปˆเบฒเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™. เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบฐเบซเบ™เบฒเบ™เปƒเบŠเป‰เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบžเบทเป‰เบ™เบ–เบฒเบ™ เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เบžเบทเป‰เบ™เบซเบผเบฑเบ‡เปเบšเบšเป€เบ„เบทเปˆเบญเบ™เป„เบซเบง (เบˆเบฒเบเบฎเบธเปˆเบ™ 9.4). เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบžเบฒเบเบชเปˆเบงเบ™เบญเบทเปˆเบ™เป†เบ‚เบญเบ‡ PostgreSQL เปƒเบŠเป‰เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบซเบผเบฒเบเบเบงเปˆเบฒเบเบฐเบ—เบนเป‰, เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ—เบตเปˆเบกเบต 3 เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เบญเบฒเบ”เบˆเบฐเป„เบงเบเบงเปˆเบฒเบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เปเบšเบšเบ”เบฑเป‰เบ‡เป€เบ”เบตเบก 4 เป€เบ—เบปเปˆเบฒ.

เบเบฒเบ™เบžเบปเบงเบžเบฑเบ™เบฎเปˆเบงเบกเบเบฑเบ™

เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบœเบนเป‰เบญเบญเบเปเบฎเบ‡เบ‡เบฒเบ™เบ•เบดเบ”เบ•เปเปˆเบชเบทเปˆเบชเบฒเบ™เบเบฑเบšเบœเบนเป‰เบ™เปเบฒเป‚เบ”เบเบœเปˆเบฒเบ™เปเบ–เบงเบ‚เปเป‰เบ„เบงเบฒเบก (เบญเบตเบ‡เปƒเบชเปˆเบ„เบงเบฒเบกเบŠเบปเบ‡เบˆเปเบฒเบฎเปˆเบงเบกเบเบฑเบ™). เปเบ•เปˆเบฅเบฐเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบกเบต 2 เบ„เบดเบง: เบชเปเบฒเบฅเบฑเบšเบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เปเบฅเบฐ tuples.

เบ•เป‰เบญเบ‡เบเบฒเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบซเบผเบฒเบเบ›เบฒเบ™เปƒเบ”?

เบ‚เบญเบšเป€เบ‚เบ”เบˆเปเบฒเบเบฑเบ”เบ•เปเบฒเปˆเบชเบธเบ”เบ—เบตเปˆเบ–เบทเบเบเปเบฒเบ™เบปเบ”เป‚เบ”เบเบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต max_parallel_workers_per_gather. เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, เบœเบนเป‰เปเบฅเปˆเบ™เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเป€เบญเบปเบฒเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบœเบนเป‰เบญเบญเบเปเบฎเบ‡เบ‡เบฒเบ™เบˆเบฒเบเบชเบฐเบ™เบธเบเป€เบเบตเบ—เบตเปˆเบˆเปเบฒเบเบฑเบ”เป‚เบ”เบเบžเบฒเบฅเบฒเบกเบดเป€เบ•เบต max_parallel_workers size. เบ‚เปเป‰เบˆเปเบฒเบเบฑเบ”เบชเบธเบ”เบ—เป‰เบฒเบเปเบกเปˆเบ™ max_worker_processes, เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เบˆเปเบฒเบ™เบงเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบทเป‰เบ™เบ–เบฒเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”.

เบ–เป‰เบฒเบšเปเปˆเบชเบฒเบกเบฒเบ”เบˆเบฑเบ”เบชเบฑเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ„เบปเบ™เบ‡เบฒเบ™เป„เบ”เป‰, เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบˆเบฐเป€เบ›เบฑเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ”เบฝเบง.

เบœเบนเป‰เบงเบฒเบ‡เปเบœเบ™เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบชเบฒเบกเบฒเบ”เบซเบผเบธเบ”เบœเปˆเบญเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเป‚เบ”เบเบญเบตเบ‡เบ•เบฒเบกเบ‚เบฐเบซเบ™เบฒเบ”เบ‚เบญเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบซเบผเบทเบ”เบฑเบ”เบชเบฐเบ™เบต. เบกเบตเบ•เบปเบงเบเปเบฒเบ™เบปเบ”เบเบฒเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰ min_parallel_table_scan_size ะธ min_parallel_index_scan_size.

set min_parallel_table_scan_size='8MB'
8MB table => 1 worker
24MB table => 2 workers
72MB table => 3 workers
x => log(x / min_parallel_table_scan_size) / log(3) + 1 worker

เบ—เบธเบเป†เบ„เบฑเป‰เบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปƒเบซเบเปˆเบเบงเปˆเบฒ 3 เป€เบ—เบปเปˆเบฒ min_parallel_(index|table)_scan_size, Postgres เป€เบžเบตเปˆเบกเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™. เบˆเปเบฒเบ™เบงเบ™เบ‚เบญเบ‡เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบšเปเปˆเป„เบ”เป‰เบญเบตเบ‡เปƒเบชเปˆเบ„เปˆเบฒเปƒเบŠเป‰เบˆเปˆเบฒเบ. เบเบฒเบ™เบ‚เบทเป‰เบ™เบเบฑเบšเบงเบปเบ‡เบงเบฝเบ™เป€เบฎเบฑเบ”เปƒเบซเป‰เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ—เบตเปˆเบชเบฑเบšเบชเบปเบ™เบกเบตเบ„เบงเบฒเบกเบซเบเบธเป‰เบ‡เบเบฒเบ. เปเบ—เบ™เบ—เบตเปˆเบˆเบฐ, เบœเบนเป‰เบงเบฒเบ‡เปเบœเบ™เปƒเบŠเป‰เบเบปเบ”เบฅเบฐเบšเบฝเบšเบ‡เปˆเบฒเบเป†.

เปƒเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”, เบเบปเบ”เบฅเบฐเบšเบฝเบšเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบšเปเปˆเบชเบฐเป€เบซเบกเบตเป„เบ›เบ—เบตเปˆเป€เบซเบกเบฒเบฐเบชเบปเบกเบเบฑเบšเบเบฒเบ™เบœเบฐเบฅเบดเบ”, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ›เปˆเบฝเบ™เบˆเปเบฒเบ™เบงเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เบชเปเบฒเบฅเบฑเบšเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบชเบฐเป€เบžเบฒเบฐ: ALTER TABLE ... SET (parallel_workers = N).

เป€เบ›เบฑเบ™เบซเบเบฑเบ‡เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบฐเบซเบ™เบฒเบ™เบˆเบถเปˆเบ‡เบšเปเปˆเบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰?

เบ™เบญเบเป€เบซเบ™เบทเบญเป„เบ›เบˆเบฒเบเบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบเบฒเบงเบ‚เบญเบ‡เบ‚เปเป‰เบˆเปเบฒเบเบฑเบ”, เบเบฑเบ‡เบกเบตเบเบฒเบ™เบเบงเบ”เบชเบญเบšเบ„เปˆเบฒเปƒเบŠเป‰เบˆเปˆเบฒเบ:

parallel_setup_cost - เป€เบžเบทเปˆเบญเบซเบผเบตเบเป€เบงเบฑเป‰เบ™เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเบซเบ™เบฒเบ™เบ‚เบญเบ‡เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเบชเบฑเป‰เบ™. เบžเบฒเบฅเบฒเบกเบดเป€เบ•เบตเบ™เบตเป‰เบ„เบฒเบ”เบ„เบฐเป€เบ™เป€เบงเบฅเบฒเปƒเบ™เบเบฒเบ™เบเบฐเบเบฝเบกเบ„เบงเบฒเบกเบŠเบปเบ‡เบˆเปเบฒ, เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™, เปเบฅเบฐเบเบฒเบ™เปเบฅเบเบ›เปˆเบฝเบ™เบ‚เปเป‰เบกเบนเบ™เป€เบšเบทเป‰เบญเบ‡เบ•เบปเป‰เบ™.

parallel_tuple_cost: เบเบฒเบ™เบชเบทเปˆเบชเบฒเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡เบœเบนเป‰เบ™เปเบฒเปเบฅเบฐเบœเบนเป‰เบญเบญเบเปเบฎเบ‡เบ‡เบฒเบ™เบชเบฒเบกเบฒเบ”เบŠเบฑเบเบŠเป‰เบฒเปƒเบ™เบญเบฑเบ”เบ•เบฒเบชเปˆเบงเบ™เบ‚เบญเบ‡เบˆเปเบฒเบ™เบงเบ™ tuples เบˆเบฒเบเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบ. เบžเบฒเบฅเบฒเบกเบดเป€เบ•เบตเบ™เบตเป‰เบ„เบดเบ”เป„เบฅเปˆเบ„เปˆเบฒเปƒเบŠเป‰เบˆเปˆเบฒเบเบ‚เบญเบ‡เบเบฒเบ™เปเบฅเบเบ›เปˆเบฝเบ™เบ‚เปเป‰เบกเบนเบ™.

Nested Loop Joins

PostgreSQL 9.6+ ะผะพะถะตั‚ ะฒั‹ะฟะพะปะฝัั‚ัŒ ะฒะปะพะถะตะฝะฝั‹ะต ั†ะธะบะปั‹ ะฟะฐั€ะฐะปะปะตะปัŒะฝะพ โ€” ัั‚ะพ ะฟั€ะพัั‚ะฐั ะพะฟะตั€ะฐั†ะธั.

explain (costs off) select c_custkey, count(o_orderkey)
                from    customer left outer join orders on
                                c_custkey = o_custkey and o_comment not like '%special%deposits%'
                group by c_custkey;
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Finalize GroupAggregate
   Group Key: customer.c_custkey
   ->  Gather Merge
         Workers Planned: 4
         ->  Partial GroupAggregate
               Group Key: customer.c_custkey
               ->  Nested Loop Left Join
                     ->  Parallel Index Only Scan using customer_pkey on customer
                     ->  Index Scan using idx_orders_custkey on orders
                           Index Cond: (customer.c_custkey = o_custkey)
                           Filter: ((o_comment)::text !~~ '%special%deposits%'::text)

เบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเป€เบเบตเบ”เบ‚เบถเป‰เบ™เปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบชเบธเบ”เบ—เป‰เบฒเบ, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™ Nested Loop Left Join เปเบกเปˆเบ™เบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™. Parallel Index Only Scan เป„เบ”เป‰เบ–เบทเบเบ™เปเบฒเบชเบฐเป€เบซเบ™เบตเบžเบฝเบ‡เปเบ•เปˆเปƒเบ™เบฎเบธเปˆเบ™ 10. เบกเบฑเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™เบเบฑเบšเบเบฒเบ™เบชเบฐเปเบเบ™ serial เบ‚เบฐเบซเบ™เบฒเบ™. เบชเบฐเบžเบฒเบš c_custkey = o_custkey เบญเปˆเบฒเบ™เบ„เปเบฒเบชเบฑเปˆเบ‡เบซเบ™เบถเปˆเบ‡เบ•เปเปˆเบชเบฒเบเบฅเบนเบเบ„เป‰เบฒ. เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบกเบฑเบ™เบšเปเปˆเปเบกเปˆเบ™เบ‚เบฐเบซเบ™เบฒเบ™.

Hash เป€เบ‚เบปเป‰เบฒเบฎเปˆเบงเบก

เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เปเบ•เปˆเบฅเบฐเบ„เบปเบ™เบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ hash เบ‚เบญเบ‡เบ•เบปเบ™เป€เบญเบ‡เบˆเบปเบ™เบเปˆเบงเบฒ PostgreSQL 11. เปเบฅเบฐเบ–เป‰เบฒเบกเบตเบซเบผเบฒเบเบเบงเปˆเบฒเบชเบตเปˆเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰, เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบˆเบฐเบšเปเปˆเบ›เบฑเบšเบ›เบธเบ‡. เปƒเบ™เบชเบฐเบšเบฑเบšเปƒเบซเบกเปˆ, เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ hash เป„เบ”เป‰เบ–เบทเบเปเบšเปˆเบ‡เบ›เบฑเบ™. เปเบ•เปˆเบฅเบฐเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ‚เบญเบ‡เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เบชเบฒเบกเบฒเบ”เปƒเบŠเป‰ WORK_MEM เป€เบžเบทเปˆเบญเบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ hash.

select
        l_shipmode,
        sum(case
                when o_orderpriority = '1-URGENT'
                        or o_orderpriority = '2-HIGH'
                        then 1
                else 0
        end) as high_line_count,
        sum(case
                when o_orderpriority <> '1-URGENT'
                        and o_orderpriority <> '2-HIGH'
                        then 1
                else 0
        end) as low_line_count
from
        orders,
        lineitem
where
        o_orderkey = l_orderkey
        and l_shipmode in ('MAIL', 'AIR')
        and l_commitdate < l_receiptdate
        and l_shipdate < l_commitdate
        and l_receiptdate >= date '1996-01-01'
        and l_receiptdate < date '1996-01-01' + interval '1' year
group by
        l_shipmode
order by
        l_shipmode
LIMIT 1;
                                                                                                                                    QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=1964755.66..1964961.44 rows=1 width=27) (actual time=7579.592..7922.997 rows=1 loops=1)
   ->  Finalize GroupAggregate  (cost=1964755.66..1966196.11 rows=7 width=27) (actual time=7579.590..7579.591 rows=1 loops=1)
         Group Key: lineitem.l_shipmode
         ->  Gather Merge  (cost=1964755.66..1966195.83 rows=28 width=27) (actual time=7559.593..7922.319 rows=6 loops=1)
               Workers Planned: 4
               Workers Launched: 4
               ->  Partial GroupAggregate  (cost=1963755.61..1965192.44 rows=7 width=27) (actual time=7548.103..7564.592 rows=2 loops=5)
                     Group Key: lineitem.l_shipmode
                     ->  Sort  (cost=1963755.61..1963935.20 rows=71838 width=27) (actual time=7530.280..7539.688 rows=62519 loops=5)
                           Sort Key: lineitem.l_shipmode
                           Sort Method: external merge  Disk: 2304kB
                           Worker 0:  Sort Method: external merge  Disk: 2064kB
                           Worker 1:  Sort Method: external merge  Disk: 2384kB
                           Worker 2:  Sort Method: external merge  Disk: 2264kB
                           Worker 3:  Sort Method: external merge  Disk: 2336kB
                           ->  Parallel Hash Join  (cost=382571.01..1957960.99 rows=71838 width=27) (actual time=7036.917..7499.692 rows=62519 loops=5)
                                 Hash Cond: (lineitem.l_orderkey = orders.o_orderkey)
                                 ->  Parallel Seq Scan on lineitem  (cost=0.00..1552386.40 rows=71838 width=19) (actual time=0.583..4901.063 rows=62519 loops=5)
                                       Filter: ((l_shipmode = ANY ('{MAIL,AIR}'::bpchar[])) AND (l_commitdate < l_receiptdate) AND (l_shipdate < l_commitdate) AND (l_receiptdate >= '1996-01-01'::date) AND (l_receiptdate < '1997-01-01 00:00:00'::timestamp without time zone))
                                       Rows Removed by Filter: 11934691
                                 ->  Parallel Hash  (cost=313722.45..313722.45 rows=3750045 width=20) (actual time=2011.518..2011.518 rows=3000000 loops=5)
                                       Buckets: 65536  Batches: 256  Memory Usage: 3840kB
                                       ->  Parallel Seq Scan on orders  (cost=0.00..313722.45 rows=3750045 width=20) (actual time=0.029..995.948 rows=3000000 loops=5)
 Planning Time: 0.977 ms
 Execution Time: 7923.770 ms

Query 12 เบˆเบฒเบ TPC-H เบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™เบขเปˆเบฒเบ‡เบŠเบฑเบ”เป€เบˆเบ™เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ hash เบ‚เบฐเบซเบ™เบฒเบ™. เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เปเบ•เปˆเบฅเบฐเบ„เบปเบ™เบ›เบฐเบเบญเบšเบชเปˆเบงเบ™เป€เบ‚เบปเป‰เบฒเปƒเบ™เบเบฒเบ™เบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ hash เบ—เบปเปˆเบงเป„เบ›.

เบฎเบงเบกเป€เบ‚เบปเป‰เบฒเบฎเปˆเบงเบก

เบเบฒเบ™เบฅเบงเบกเป€เบ‚เบปเป‰เบฒเบเบฑเบ™เบšเปเปˆเปเบกเปˆเบ™เปเบšเบšเบ‚เบฐเปœเบฒเบ™เบเบฑเบ™. เบขเปˆเบฒเบเบฑเบ‡เบงเบปเบ™เบงเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบชเบธเบ”เบ—เป‰เบฒเบเบ‚เบญเบ‡เบเบฒเบ™เบชเบญเบšเบ–เบฒเบก - เบกเบฑเบ™เบเบฑเบ‡เบชเบฒเบกเบฒเบ”เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™เป„เบ”เป‰.

-- Query 2 from TPC-H
explain (costs off) select s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment
from    part, supplier, partsupp, nation, region
where
        p_partkey = ps_partkey
        and s_suppkey = ps_suppkey
        and p_size = 36
        and p_type like '%BRASS'
        and s_nationkey = n_nationkey
        and n_regionkey = r_regionkey
        and r_name = 'AMERICA'
        and ps_supplycost = (
                select
                        min(ps_supplycost)
                from    partsupp, supplier, nation, region
                where
                        p_partkey = ps_partkey
                        and s_suppkey = ps_suppkey
                        and s_nationkey = n_nationkey
                        and n_regionkey = r_regionkey
                        and r_name = 'AMERICA'
        )
order by s_acctbal desc, n_name, s_name, p_partkey
LIMIT 100;
                                                QUERY PLAN
----------------------------------------------------------------------------------------------------------
 Limit
   ->  Sort
         Sort Key: supplier.s_acctbal DESC, nation.n_name, supplier.s_name, part.p_partkey
         ->  Merge Join
               Merge Cond: (part.p_partkey = partsupp.ps_partkey)
               Join Filter: (partsupp.ps_supplycost = (SubPlan 1))
               ->  Gather Merge
                     Workers Planned: 4
                     ->  Parallel Index Scan using <strong>part_pkey</strong> on part
                           Filter: (((p_type)::text ~~ '%BRASS'::text) AND (p_size = 36))
               ->  Materialize
                     ->  Sort
                           Sort Key: partsupp.ps_partkey
                           ->  Nested Loop
                                 ->  Nested Loop
                                       Join Filter: (nation.n_regionkey = region.r_regionkey)
                                       ->  Seq Scan on region
                                             Filter: (r_name = 'AMERICA'::bpchar)
                                       ->  Hash Join
                                             Hash Cond: (supplier.s_nationkey = nation.n_nationkey)
                                             ->  Seq Scan on supplier
                                             ->  Hash
                                                   ->  Seq Scan on nation
                                 ->  Index Scan using idx_partsupp_suppkey on partsupp
                                       Index Cond: (ps_suppkey = supplier.s_suppkey)
               SubPlan 1
                 ->  Aggregate
                       ->  Nested Loop
                             Join Filter: (nation_1.n_regionkey = region_1.r_regionkey)
                             ->  Seq Scan on region region_1
                                   Filter: (r_name = 'AMERICA'::bpchar)
                             ->  Nested Loop
                                   ->  Nested Loop
                                         ->  Index Scan using idx_partsupp_partkey on partsupp partsupp_1
                                               Index Cond: (part.p_partkey = ps_partkey)
                                         ->  Index Scan using supplier_pkey on supplier supplier_1
                                               Index Cond: (s_suppkey = partsupp_1.ps_suppkey)
                                   ->  Index Scan using nation_pkey on nation nation_1
                                         Index Cond: (n_nationkey = supplier_1.s_nationkey)

เป‚เบซเบ™เบ” "Merge Join" เบ•เบฑเป‰เบ‡เบขเบนเปˆเบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡ "Gather Merge". เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™เบฅเบงเบกเบ•เบปเบงเบšเปเปˆเป„เบ”เป‰เปƒเบŠเป‰เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบฐเบซเบ™เบฒเบ™. เปเบ•เปˆ "Parallel Index Scan" node เบเบฑเบ‡เบŠเปˆเบงเบเปƒเบ™เบชเปˆเบงเบ™ part_pkey.

เบเบฒเบ™โ€‹เป€เบŠเบทเปˆเบญเบกโ€‹เบ•เปเปˆโ€‹เป‚เบ”เบโ€‹เบžเบฒเบโ€‹เบชเปˆเบงเบ™โ€‹

เปƒเบ™ PostgreSQL 11 เบเบฒเบ™โ€‹เป€เบŠเบทเปˆเบญเบกโ€‹เบ•เปเปˆโ€‹เป‚เบ”เบโ€‹เบžเบฒเบโ€‹เบชเปˆเบงเบ™โ€‹ เบ›เบดเบ”เบเบฒเบ™เปƒเบŠเป‰เบ‡เบฒเบ™เป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™: เบกเบฑเบ™เบกเบตเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบฅเบฒเบ„เบฒเปเบžเบ‡เบซเบผเบฒเบ. เบ•เบฒโ€‹เบ•เบฐโ€‹เบฅเบฒเบ‡โ€‹เบ—เบตเปˆโ€‹เบกเบตโ€‹เบเบฒเบ™โ€‹เปเบšเปˆเบ‡โ€‹เบ›เบฑเบ™โ€‹เบ—เบตเปˆโ€‹เบ„เป‰เบฒเบโ€‹เบ„เบทโ€‹เบเบฑเบ™โ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เป€เบ‚เบปเป‰เบฒโ€‹เบฎเปˆเบงเบกโ€‹เบเบฒเบ™โ€‹เปเบšเปˆเบ‡โ€‹เบ›เบฑเบ™โ€‹เป‚เบ”เบโ€‹เบเบฒเบ™โ€‹เปเบšเปˆเบ‡โ€‹เบ›เบฑเบ™โ€‹. เบงเบดเบ—เบตเบ™เบตเป‰ Postgres เบˆเบฐเปƒเบŠเป‰เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ hash เบ‚เบฐเบซเบ™เบฒเบ”เบ™เป‰เบญเบเบเบงเปˆเบฒ. เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปเบ•เปˆเบฅเบฐเบžเบฒเบเบชเปˆเบงเบ™เบชเบฒเบกเบฒเบ”เบ‚เบฐเบซเบ™เบฒเบ™เป„เบ”เป‰.

tpch=# set enable_partitionwise_join=t;
tpch=# explain (costs off) select * from prt1 t1, prt2 t2
where t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;
                    QUERY PLAN
---------------------------------------------------
 Append
   ->  Hash Join
         Hash Cond: (t2.b = t1.a)
         ->  Seq Scan on prt2_p1 t2
               Filter: ((b >= 0) AND (b <= 10000))
         ->  Hash
               ->  Seq Scan on prt1_p1 t1
                     Filter: (b = 0)
   ->  Hash Join
         Hash Cond: (t2_1.b = t1_1.a)
         ->  Seq Scan on prt2_p2 t2_1
               Filter: ((b >= 0) AND (b <= 10000))
         ->  Hash
               ->  Seq Scan on prt1_p2 t1_1
                     Filter: (b = 0)
tpch=# set parallel_setup_cost = 1;
tpch=# set parallel_tuple_cost = 0.01;
tpch=# explain (costs off) select * from prt1 t1, prt2 t2
where t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;
                        QUERY PLAN
-----------------------------------------------------------
 Gather
   Workers Planned: 4
   ->  Parallel Append
         ->  Parallel Hash Join
               Hash Cond: (t2_1.b = t1_1.a)
               ->  Parallel Seq Scan on prt2_p2 t2_1
                     Filter: ((b >= 0) AND (b <= 10000))
               ->  Parallel Hash
                     ->  Parallel Seq Scan on prt1_p2 t1_1
                           Filter: (b = 0)
         ->  Parallel Hash Join
               Hash Cond: (t2.b = t1.a)
               ->  Parallel Seq Scan on prt2_p1 t2
                     Filter: ((b >= 0) AND (b <= 10000))
               ->  Parallel Hash
                     ->  Parallel Seq Scan on prt1_p1 t1
                           Filter: (b = 0)

เบชเบดเปˆเบ‡เบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™เปเบกเปˆเบ™เบงเปˆเบฒเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปƒเบ™เบžเบฒเบเบชเปˆเบงเบ™เบ•เปˆเบฒเบ‡เป†เปเบกเปˆเบ™เบ‚เบฐเบซเบ™เบฒเบ™เบžเบฝเบ‡เปเบ•เปˆเบ–เป‰เบฒเบžเบฒเบเบชเปˆเบงเบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบกเบตเบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆเบžเบฝเบ‡เบžเป.

Parallel Append

Parallel Append เบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เปเบ—เบ™ blocks เบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เปƒเบ™ workflows เบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™. เบ™เบตเป‰เบกเบฑเบเบˆเบฐเป€เบเบตเบ”เบ‚เบถเป‰เบ™เบเบฑเบš UNION ALL queries. เบ‚เปเป‰เป€เบชเบเปเบกเปˆเบ™เบ„เบงเบฒเบกเบ‚เบฐเปœเบฒเบ™เปœเป‰เบญเบ, เป€เบžเบฒเบฐเบงเปˆเบฒเปเบ•เปˆเบฅเบฐเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ„เบปเบ™เบ‡เบฒเบ™เบžเบฝเบ‡เปเบ•เปˆเบ”เบณเป€เบ™เบตเบ™เบเบฒเบ™ 1 เบ„เบณเบฎเป‰เบญเบ‡เบ‚เป.

เบกเบต 2 เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เปเบฅเปˆเบ™เบขเบนเปˆเบ—เบตเปˆเบ™เบตเป‰, เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒ 4 เบˆเบฐเบ–เบทเบเป€เบ›เบตเบ”เปƒเบŠเป‰.

tpch=# explain (costs off) select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day union all select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '2000-12-01' - interval '105' day;
                                           QUERY PLAN
------------------------------------------------------------------------------------------------
 Gather
   Workers Planned: 2
   ->  Parallel Append
         ->  Aggregate
               ->  Seq Scan on lineitem
                     Filter: (l_shipdate <= '2000-08-18 00:00:00'::timestamp without time zone)
         ->  Aggregate
               ->  Seq Scan on lineitem lineitem_1
                     Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)

เบ•เบปเบงเปเบ›เบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™เบ—เบตเปˆเบชเบธเบ”

  • WORK_MEM เบˆเบณเบเบฑเบ”เบ„เบงเบฒเบกเบˆเบณเบ•เปเปˆเบ‚เบฐเบšเบงเบ™เบเบฒเบ™, เบšเปเปˆเบžเบฝเบ‡เปเบ•เปˆเบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเป€เบ—เบปเปˆเบฒเบ™เบฑเป‰เบ™: work_mem เบ‚เบฐเบšเบงเบ™เบเบฒเบ™ เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ = เบ„เบงเบฒเบกเบˆเปเบฒเบซเบผเบฒเบ.
  • max_parallel_workers_per_gather โ€” เบกเบตเบˆเบฑเบเบ„เบปเบ™เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบ—เบตเปˆเป‚เบ„เบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบˆเบฐเปƒเบŠเป‰เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเบซเบ™เบฒเบ™เบˆเบฒเบเปเบœเบ™เบเบฒเบ™.
  • max_worker_processes โ€” เบ›เบฑเบšโ€‹เบˆเปเบฒโ€‹เบ™เบงเบ™โ€‹เบ‚เบฐโ€‹เบšเบงเบ™โ€‹เบเบฒเบ™โ€‹เบžเบฐโ€‹เบ™เบฑเบโ€‹เบ‡เบฒเบ™โ€‹เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เบเบฑเบšโ€‹เบˆเปเบฒโ€‹เบ™เบงเบ™โ€‹เบ‚เบญเบ‡ CPU cores เปƒเบ™โ€‹เป€เบ„เบทเปˆเบญเบ‡โ€‹เปเบกเปˆโ€‹เบ‚เปˆเบฒเบโ€‹.
  • max_parallel_workers - เบ”เบฝเบงเบเบฑเบ™, เปเบ•เปˆเบชเปเบฒเบฅเบฑเบšเบ‚เบฐเบšเบงเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ‚เบฐเบซเบ™เบฒเบ™.

เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบš

เปƒเบ™เบ–เบฒเบ™เบฐเป€เบ›เบฑเบ™เบชเบฐเบšเบฑเบš 9.6, เบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบ‚เบฐเบซเบ™เบฒเบ™เบขเปˆเบฒเบ‡เบซเบผเบงเบ‡เบซเบผเบฒเบเบชเบฒเบกเบฒเบ”เบ›เบฑเบšเบ›เบธเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบชเบฐเบฅเบฑเบšเบชเบฑเบšเบŠเป‰เบญเบ™เบ—เบตเปˆเบชเบฐเปเบเบ™เบซเบผเบฒเบเปเบ–เบงเบซเบผเบทเบ”เบฑเบ”เบชเบฐเบ™เบต. เปƒเบ™ PostgreSQL 10, เบเบฒเบ™เบ›เบฐเบกเบงเบ™เบœเบปเบ™เบ‚เบฐเปœเบฒเบ™เบˆเบฐเบ–เบทเบเป€เบ›เบตเบ”เปƒเบŠเป‰เป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™. เบขเปˆเบฒเบฅเบทเบกเบ›เบดเบ”เบเบฒเบ™เปƒเบŠเป‰เบ‡เบฒเบ™เบกเบฑเบ™เบขเบนเปˆเปƒเบ™เป€เบŠเบตเบšเป€เบงเบตเบ—เบตเปˆเบกเบตเบงเบฝเบ OLTP เบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆ. เบเบฒเบ™เบชเบฐเปเบเบ™เบ•เบฒเบกเบฅเปเบฒเบ”เบฑเบšเบซเบผเบทเบเบฒเบ™เบชเบฐเปเบเบ™เบ”เบฑเบ”เบชเบฐเบ™เบตเปƒเบŠเป‰เบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เบซเบผเบฒเบ. เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบšเปเปˆเป„เบ”เป‰เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบฅเบฒเบเบ‡เบฒเบ™เบเปˆเบฝเบงเบเบฑเบšเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ›เบฑเบšเบ›เบธเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเป‚เบ”เบเบžเบฝเบ‡เปเบ•เปˆเป€เบžเบตเปˆเบกเบ”เบฑเบ”เบชเบฐเบ™เบตเบ—เบตเปˆเบ‚เบฒเบ”เบซเบฒเบเป„เบ›เบซเบผเบทเปƒเบŠเป‰เบเบฒเบ™เปเบšเปˆเบ‡เบ›เบฑเบ™เบ—เบตเปˆเป€เบซเบกเบฒเบฐเบชเบปเบก.

เป€เบญเบเบฐเบชเบฒเบ™

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™