ฉันจะทราบได้อย่างไรว่าแบบสอบถาม PostgreSQL ของฉันอยู่ไกลแค่ไหน?


35

ฉันมีความคิดที่ดีว่าจำนวนคิวรี SELECT ของฉัน ... เข้าสู่กระบวนการจริงจะดำเนินการอย่างไร (เช่นฉันรู้ว่าจะปรากฏเป็นรูปเป็นร่างเท่าใด)

ฉันเข้าใจว่า Postgres จะไม่บอกเปอร์เซ็นต์ความครบถ้วนสมบูรณ์มีวิธี (ฝังลึกในบันทึก, ตารางระบบหรืออื่น ๆ ) ที่ฉันสามารถค้นหาจำนวนแถวที่ถูกปั๊มเข้าไปในตารางปลายทางหรืออ่านโดยเลือกคิวรี่ ?

คำตอบ:


33

ดังที่ Daniel Véritéพูดถึงดูเหมือนจะไม่มีทางแก้ปัญหาทั่วไป เมื่อโหลดข้อมูลลงในตารางจากไฟล์เทคนิคต่อไปนี้สามารถใช้เพื่อรับความคืบหน้าของการโหลด

แถบความคืบหน้าของคอนโซลคำสั่ง COPY

สร้างตารางที่ว่างเปล่า

CREATE TABLE mytest (n int);

สร้างไฟล์ข้อมูลที่มี 10 ล้านบรรทัดสำหรับการโหลดลงในตาราง

$ seq 10000000 > /tmp/data.txt

โหลดข้อมูลจากไฟล์ลงในตารางและแสดงแถบความคืบหน้า

$ pv /tmp/data.txt | psql -c "COPY mytest FROM STDIN;"

การสาธิต

ป้อนคำอธิบายรูปภาพที่นี่

วิธีนี้ใช้ได้ผล

โดยใช้ตัวเลือกคำสั่งคัดลอก STDIN เราสามารถป้อนข้อมูลสำหรับการดำเนินการคัดลอกจากกระบวนการอื่น คำสั่ง pv จะส่งออกไฟล์และติดตามความคืบหน้าโดยแสดงแถบความคืบหน้า ETA เวลาที่ผ่านไปทั้งหมดและอัตราการถ่ายโอนข้อมูล

แถบความคืบหน้ากราฟิกคำสั่ง COPY

การใช้เทคนิคทั่วไปเดียวกันเราสามารถแสดงแถบความคืบหน้าในแอปพลิเคชันกราฟิกหรือแอปพลิเคชันบนเว็บ การใช้ไพ ธ อนตัวอย่างเช่นโมดูลpsycopg2ให้คุณเรียกคำสั่ง copy ด้วยอ็อบเจ็กต์ไฟล์ที่คุณเลือก จากนั้นคุณสามารถติดตามจำนวนไฟล์วัตถุที่ถูกอ่านและแสดงแถบความคืบหน้า


2
ฉันไม่เคยเจอpvคำสั่งมาก่อนและไม่ได้ติดตั้งบนเซิร์ฟเวอร์ Debian ของฉันตามค่าเริ่มต้น แต่อยู่ใน repo คำอธิบายกล่าวว่า "pv (Pipe Viewer) สามารถแทรกลงในไปป์ไลน์ปกติใด ๆ ระหว่างสองกระบวนการเพื่อให้การบ่งชี้ที่มองเห็นได้ว่าข้อมูลกำลังผ่านไปเร็วแค่ไหน" คำสั่งที่มีประโยชน์มาก!
Richard Turner

27

ดูเหมือนจะไม่มีวิธีทั่วไปที่ได้รับการสนับสนุน แต่มีเทคนิคบางอย่างที่อาจใช้ในบริบทที่ จำกัด เพื่อประเมินความคืบหน้าของแบบสอบถามแต่ละรายการ นี่คือบางส่วนของพวกเขา

ลำดับ

เมื่อแบบสอบถาม SELECT หรือรวมถึงการปรับปรุงใด ๆnextval(sequence_name)หรือ INSERT มีคอลัมน์ปลายทางที่มีเป็นค่าเริ่มต้นค่าลำดับปัจจุบันสามารถสอบถามซ้ำแล้วซ้ำอีกในเซสชั่นอีกด้วยnextval SELECT sequence_name.last_valueมันทำงานได้เพราะลำดับไม่ได้ถูกล้อมรอบด้วยการทำธุรกรรม เมื่อแผนการดำเนินการเป็นเช่นนั้นลำดับจะเพิ่มขึ้นเป็นเส้นตรงในระหว่างการสืบค้นสามารถใช้เป็นตัวบ่งชี้ความคืบหน้าได้

pgstattuple

pgstattupleโมดูล contrib ให้ฟังก์ชั่นที่สามารถมองได้โดยตรงที่หน้าข้อมูล ปรากฏว่าเมื่อใส่สิ่งอันดับลงในตารางว่างเปล่าและยังไม่ได้ส่งข้อมูลจะถูกนับในdead_tuple_countฟิลด์จากpgstattupleฟังก์ชัน

การสาธิตด้วย 9.1: สร้างตารางว่าง

CREATE TABLE tt AS (n numeric);

ลองแทรก 10M แถวเข้าไป:

INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);

ในเซสชั่นอื่นให้ตรวจสอบ pgstattuple ทุกวินาทีในระหว่างการแทรก:

$ while true;
   do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
   sleep 1;
  done

ผล:

0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0

มันกลับไปที่ 0 เมื่อแทรกเสร็จแล้ว (tuples ทั้งหมดจะมองเห็นและมีชีวิตอยู่)

เคล็ดลับนี้อาจใช้เมื่อตารางไม่ได้สร้างขึ้นใหม่ แต่ค่าเริ่มต้นdead_tuple_countน่าจะมีค่าที่ไม่เป็นศูนย์และอาจเปลี่ยนพร้อมกันหากกิจกรรมการเขียนอื่นเช่น autovacuum เกิดขึ้น (สมมุติหรือไม่ไม่แน่ใจว่าระดับของ ภาวะพร้อมกันที่คาดหวังด้วย autovacuum)

อย่างไรก็ตามมันไม่สามารถใช้ถ้าตารางถูกสร้างขึ้นโดยคำสั่งตัวเอง ( CREATE TABLE ... AS SELECTหรือSELECT * INTO newtable) เนื่องจากการสร้างการทำธุรกรรม วิธีแก้ปัญหาคือการสร้างตารางโดยไม่มีแถว (เพิ่มLIMIT 0) และเติมข้อมูลในธุรกรรมถัดไป

โปรดทราบpgstattupleว่าไม่ได้มาฟรี: สแกนตารางทั้งหมดทุกการโทร นอกจากนี้ยัง จำกัด เฉพาะผู้ใช้ระดับสูง

เคาน์เตอร์ที่กำหนดเอง

ในบล็อกของ Pavel Stehule เขามีฟังก์ชั่นตัวนับ นำมาใช้ใน C ที่เพิ่มข้อสังเกตตามจำนวนการประหารชีวิตที่ระบุ คุณต้องรวมฟังก์ชั่นเข้ากับเคียวรีเพื่อให้ผู้ปฏิบัติการเรียกมัน การแจ้งเตือนจะถูกส่งไประหว่างการสืบค้นและไม่จำเป็นต้องแยกเซสชันเฉพาะไคลเอ็นต์ SQL ที่แสดงพวกเขา ( psqlเป็นตัวเลือกที่ชัดเจน)

ตัวอย่างของ INSERT INTO ทำใหม่เพื่อเพิ่มประกาศ:

/* transformation */
INSERT INTO destination_table
   SELECT (r).*
  FROM (SELECT counter(to_destination_table(_source), 1000, true) r
           FROM source _source) x

คำถามที่เกี่ยวข้องกับ stackoverflow สำหรับฟังก์ชั่น:
วิธีการรายงานความคืบหน้าจากฟังก์ชั่น PostgreSQL ที่ทำงานมานานเพื่อลูกค้า

ตัวเลือกในอนาคต?

เมื่อวันที่พฤษภาคม 2017 มีการแพทช์ที่มีแนวโน้มส่งไปยังชุมชนนักพัฒนา: [PATCH v2] คำสั่งความคืบหน้าในการตรวจสอบความคืบหน้าของการสืบค้น SQL ยาวยาว

ซึ่งอาจเป็นโซลูชันทั่วไปใน PostgreSQL 11 หรือใหม่กว่า ผู้ใช้ที่รู้สึกว่ามีส่วนร่วมในคุณสมบัติความคืบหน้าในการทำงานอาจใช้โปรแกรมปรับปรุงรุ่นล่าสุดและลองใช้PROGRESSคำสั่งที่เสนอ


3

จนกว่าฟังก์ชันรายงานความคืบหน้าจะไม่ถูกขยายดังที่ @AmirAliAkbari พูดถึงในคำตอบของเขานี่เป็นวิธีแก้ปัญหาระดับ OS

สิ่งนี้ใช้ได้กับ Linux เท่านั้น แต่อาจมีโซลูชันที่คล้ายกัน googlable สำหรับระบบปฏิบัติการใด ๆ

ข้อได้เปรียบที่ใหญ่ที่สุดและยังเป็นข้อเสียของ PostgreSQL, ว่าทั้งหมดของแบ็กเอนด์ที่มีกระบวนการเดียว threaded ง่ายใช้lseek(), read()และwrite()การจัดการไฟล์ตารางของพวกเขาขณะที่พวกเขาจะมีปฏิสัมพันธ์ในข่าวที่ใช้ร่วมกันและล็อค

ผลลัพธ์นี้กระบวนการแบ็กเอนด์ทั้งหมดนั้นทำงานได้กับแบบสอบถามเดียวซึ่งสามารถค้นหาได้ง่ายและง่ายstraced

ก่อนอื่นคุณสามารถดู PID ของแบ็กเอนด์ได้จากSELECT * FROM pg_stat_activity;:

29805270 | dbname  | 20019 |    16384 | username  |                  |             |                 |          -1 | 2018-09-19 21:31:57.68234+02  | 2018-09-19 21:31:59.435376+02 | 2018-09-\
20 00:34:30.892382+02 | 2018-09-20 00:34:30.892386+02 | Client          | ClientRead | active              |       92778 |        92778 |  INSERT INTO ...something...

คอลัมน์ที่สามคือ pid ใน PostgreSQL มันเหมือนกับกระบวนการ Linux pid ของแบ็คเอนด์

ถัดไปคุณสามารถ strace ตัวอย่างเช่นโดยstrace -p 20019 -s 8192: ( -s 8192มีประโยชน์เนื่องจาก postgresql ทำงานกับบล็อกขนาดยาว 8192 ไบต์)

sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
recvfrom(10, "Q\0\0\1\267 INSERT <removed by @peterh>", 8192, 0, NULL, NULL) = 440
sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
lseek(298, 343634345)...
read(298, "<block data which was read in>"....
write(298, "<block data which was written out>"...

ความหมาย:

  • sendtoเกิดขึ้นถ้าส่วนแบ็คเอนด์ตอบอะไรบางอย่างกับลูกค้า ในตัวอย่างจะตอบผลลัพธ์ของINSERTแบบสอบถาม
  • recvfromเกิดขึ้นถ้าส่วนแบ็คเอนด์ได้รับบางสิ่งบางอย่างจากลูกค้า INSERTมันเป็นเรื่องปกติแบบสอบถามใหม่ในตัวอย่างอีก
  • lseek เกิดขึ้นหากแบ็กเอนด์สลับตำแหน่งในไฟล์ตาราง
  • read เกิดขึ้นหากส่วนแบ็คเอนด์อ่านบล็อกจากไฟล์ตาราง
  • write เกิดขึ้นถ้าส่วนแบ็คเอนด์เขียนบล็อกออกเป็นไฟล์ตาราง

ในกรณีของreadและwriteคุณยังสามารถดูเนื้อหาของบล็อกนั้นในตาราง มันสามารถช่วยได้มากในการทำความเข้าใจสิ่งที่กำลังทำและอยู่ที่ไหน

ในกรณีของrecvfromคุณสามารถดูคิวรีที่แท้จริงที่แบ็กเอนด์ได้


2

ดังที่ได้กล่าวไปแล้วในคำตอบอื่น ๆ ในปัจจุบันไม่มีวิธีโดยตรงสำหรับการรายงานความคืบหน้าโดยทั่วไป

PostgreSQL มีความสามารถในการรายงานความคืบหน้าของคำสั่งบางอย่างในระหว่างการดำเนินการคำสั่ง ปัจจุบันคำสั่งเดียวที่รองรับการรายงานความคืบหน้าคือ VACUUM สิ่งนี้อาจขยายได้ในอนาคต

อย่างไรก็ตามเริ่มต้นจาก 9.6 เมื่อใดก็ตามที่VACUUMทำงานpg_stat_progress_vacuumมุมมองจะมีหนึ่งแถวสำหรับแต่ละแบ็กเอนด์ (รวมถึงกระบวนการของผู้ปฏิบัติงาน autovacuum) ที่กำลังดูดฝุ่น รายละเอียดเพิ่มเติมเกี่ยวกับpg_stat_progress_vacuumสามารถพบได้ในเอกสาร: 27.4 รายงานความคืบหน้า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.