การนับแถวในตารางขนาดใหญ่เป็นที่ทราบกันดีว่า PostgreSQL ช้า เพื่อให้ได้จำนวนที่แม่นยำมันได้ทำนับเต็มรูปแบบของแถวเนื่องจากลักษณะของMVCC มีวิธีที่จะเร่งให้เร็วขึ้นอย่างมากหากการนับไม่จำเป็นต้องตรงตามที่เห็นในกรณีของคุณ
แทนที่จะได้รับการนับที่แน่นอน ( ช้าด้วยตารางขนาดใหญ่):
SELECT count(*) AS exact_count FROM myschema.mytable;
คุณจะได้ค่าประมาณใกล้เคียงเช่นนี้ ( เร็วมาก ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
การปิดประมาณการขึ้นอยู่กับว่าคุณทำงานANALYZE
เพียงพอหรือไม่ มันมักจะใกล้มาก
ดูPostgreSQL วิกิพีเดียคำถามที่พบบ่อย
หรือหน้าวิกิพีเดียทุ่มเทสำหรับการนับ (*) ผลการดำเนินงาน
ยังดีกว่า
บทความในวิกิพีเดีย PostgreSQL จะเป็นบิตเลอะเทอะ โดยไม่สนใจความเป็นไปได้ที่อาจมีหลายตารางที่มีชื่อเดียวกันในฐานข้อมูลเดียว - ในสคีมาที่ต่างกัน ในการพิจารณาเรื่องนั้น:
SELECT c.reltuples::bigint AS estimate
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'mytable'
AND n.nspname = 'myschema'
หรือยังดีกว่า
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'myschema.mytable'::regclass;
เร็วขึ้นง่ายขึ้นปลอดภัยขึ้นสง่างามมากขึ้น ดูคู่มือในวัตถุประเภทตัวบ่งชี้
ใช้to_regclass('myschema.mytable')
ใน Postgres 9.4+ เพื่อหลีกเลี่ยงข้อยกเว้นสำหรับชื่อตารางที่ไม่ถูกต้อง:
SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
เช่นเดียวกับ@a_horse แสดงความคิดเห็นอนุประโยคที่เพิ่มใหม่สำหรับSELECT
คำสั่งอาจมีประโยชน์หากสถิติในpg_class
ไม่เป็นปัจจุบันเพียงพอด้วยเหตุผลบางประการ ตัวอย่างเช่น:
- ไม่มีการ
autovacuum
วิ่ง
- ทันทีหลังจากใหญ่
INSERT
หรือDELETE
.
TEMPORARY
ตาราง (ซึ่งไม่ครอบคลุมautovacuum
)
สิ่งนี้จะดูเฉพาะการเลือกบล็อกแบบสุ่มn % ( 1
ในตัวอย่าง) และนับแถวในนั้น ตัวอย่างที่ใหญ่ขึ้นจะเพิ่มต้นทุนและลดข้อผิดพลาดให้คุณเลือก ความแม่นยำขึ้นอยู่กับปัจจัยอื่น ๆ :
- การกระจายขนาดของแถว หากบล็อกที่กำหนดมีแถวกว้างกว่าปกติจำนวนจะต่ำกว่าปกติเป็นต้น
- สิ่งที่ตายแล้วหรือ
FILLFACTOR
ใช้พื้นที่ต่อบล็อก หากกระจายทั่วทั้งโต๊ะไม่เท่ากันค่าประมาณอาจปิดอยู่
- ข้อผิดพลาดในการปัดเศษทั่วไป
ในกรณีส่วนใหญ่ค่าประมาณจากpg_class
จะรวดเร็วและแม่นยำกว่า
ตอบคำถามจริง
ก่อนอื่นฉันต้องทราบจำนวนแถวในตารางนั้นหากจำนวนรวมมากกว่าค่าคงที่ที่กำหนดไว้ล่วงหน้า
และไม่ว่าจะ ...
... เป็นไปได้ในขณะที่การนับผ่านค่าคงที่ของฉันมันจะหยุดการนับ (และไม่รอที่จะสิ้นสุดการนับเพื่อแจ้งให้ทราบจำนวนแถวที่มากขึ้น)
ใช่. คุณสามารถใช้แบบสอบถามย่อยกับLIMIT
:
SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
Postgres หยุดนับเกินขีด จำกัด ที่กำหนดจริง ๆ แล้วคุณจะได้รับการนับที่แน่นอนและปัจจุบันมากถึงnแถว (500000 ในตัวอย่าง) และnอย่างอื่น pg_class
แม้ว่าจะไม่เร็วเท่าที่คาดการณ์ไว้