เหตุใด SELECT * จึงเร็วกว่าการเลือกคอลัมน์ทั้งหมด (ตามลำดับคอลัมน์) ตามชื่อ


12

บนโต๊ะที่มีคอลัมน์ a, b, c, d, e, f, g, h, i, j, k ฉันได้รับ:

select * from misty order by a limit 25;
Time: 302.068 ms

และ:

select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;
Time: 1258.451 ms

มีวิธีในการเลือกคอลัมน์อย่างรวดเร็วหรือไม่?

ปรับปรุง:

ไม่มีดัชนีในตารางสร้างขึ้นใหม่

นี่คือการอธิบายการวิเคราะห์ดูเหมือนจะไม่เป็นประโยชน์:

explain analyze select * from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=404.958..404.971 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=404.957..404.963 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.013..170.945 rows=694686 loops=1)
Total runtime: 405.019 ms
(6 rows)

และ:

explain analyze select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=1371.735..1371.745 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=1371.733..1371.736 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.015..516.355 rows=694686 loops=1)
Total runtime: 1371.797 ms
(6 rows)

คอลัมน์เป็นดัชนีหรือไม่ คุณช่วยอธิบายโพสต์วิเคราะห์ได้ไหม?
user_0

1
คุณต้องระมัดระวังในการเลือกทั้งสองอย่างในแถวและเปรียบเทียบเวลา ข้อมูลในแคชของการสืบค้นที่สองอาจแสดงถึงความแตกต่างในเวลา
วอลเตอร์ Mitty

1
ฉันเห็นความแตกต่างเช่นกันแม้ว่าจะไม่เด่นชัด โต๊ะของฉันมีแถว = 514,431 width = 215 และฉันได้รับประมาณ 1.5s สำหรับselect *กรณีและประมาณ 2.2s สำหรับเลือกที่มีคอลัมน์ที่ระบุไว้ในลำดับที่แตกต่างกัน
Colin 't Hart

select *ถ้าฉันรายการคอลัมน์ทั้งหมดในลำดับเดียวกันตามที่กำหนดไว้ในตารางที่ฉันได้รับประมาณครั้งเช่นเดียวกับถ้าฉัน
Colin 't Hart

2
ชื่อเรื่องนั้นทำให้เข้าใจผิด คำถามคือทำไมระยะเวลาของการเรียงขึ้นอยู่กับลำดับของคอลัมน์ผลลัพธ์
Daniel Vérité

คำตอบ:


12

นี่ถูกโพสต์ไปยังรายชื่อผู้รับจดหมายของ pgsql-hackers และฉันพยายามตอบสั้น ๆ ตรงนั้น ดูเหมือนว่ารายการเป้าหมาย (คอลัมน์ที่ระบุ) ตรงกับ tuple descriptor ของความสัมพันธ์อย่างแท้จริงนั่นคือทั้งในจำนวนคอลัมน์และลำดับจากนั้นการสแกนพื้นฐานสามารถส่งคืน tuple ที่บริโภคได้โดยตรงจากโหนดเรียงที่ล้อมรอบ ในทางกลับกันหากรายการเป้าหมายไม่ตรงกัน (ตามลำดับหรือจำนวนคอลัมน์ที่ระบุ) การสแกนจะส่งคืนรูปแบบของ tuples ที่ต้องการขั้นตอนการเตรียมข้อมูลของ Sort เพื่อทำงานพิเศษ (แปลงจากรูปแบบ tuple ภายในเป็น รูปแบบสิ้นเปลืองโดยตรงโดยรหัสการเรียงลำดับ)

โดยวิธีการ '*' จะถูกแปลงภายในเป็นรายการที่ (สังหรณ์ใจ) ตรงกับตัวบ่งชี้ tuple ของความสัมพันธ์

แก้ไข: หากคุณดูเวลาหลังสุดของ EXPLAIN ANALYZE ของการวิเคราะห์ Seq Scan คุณจะเห็นว่ามันเป็นมากกว่าที่เคยเป็นมา ที่เกิดขึ้นเนื่องจากการสแกนดำเนินการขั้นตอนเพิ่มเติมของการฉายภาพ (นั่นคือการแปลง heap tuple เป็นค่าภายใน [], nulls [] รูปแบบ) และเนื่องจากสิ่งนั้นเกิดขึ้นโหนดการเรียงลำดับบนต้องทำงานพิเศษในการเริ่มต้นข้อมูลของมันการแปลงกลับเป็นรูปแบบทูเปิลที่ขั้นตอนการเรียงจริงเข้าใจ เห็นได้ชัดจากค่าเริ่มต้นของการเรียงลำดับ ที่ไม่ได้เกิดขึ้นในกรณีก่อน นั่นคือทั้งการสแกนส่งคืน tuple ตามที่เป็นอยู่และขั้นตอนการกำหนดค่าเริ่มต้นของการเรียงลำดับเพียงคัดลอก


@ Colin'tHart หวังว่ามันสมเหตุสมผล
amitlan

ใช่. ฉันหวังว่ามันจะเป็นไปได้ที่จะข้ามขั้นตอนนั้นหรือทำให้สั้นลงโดยใช้ "ตัวชี้แบบสับ" บางตัว แต่นั่นเป็นการสนทนาสำหรับ pgsql-hacker
Colin 't Hart

อาจมีการปรับปรุงบางอย่างบนขอบฟ้าด้วยการฟื้นฟูการสั่งงานคอลัมน์แบบลอจิคัลล่าสุด
amitlan

ฉันคิดถึงเรื่องนั้นอยู่แล้วและหวังเช่นนั้น!
Colin 't Hart

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