อันไหนเร็วกว่า / ดีที่สุด? SELECT * หรือ SELECT column1, colum2, column3, ฯลฯ


166

ฉันได้ยินมาว่าSELECT *เป็นวิธีปฏิบัติที่ไม่ดีที่จะใช้เมื่อเขียนคำสั่ง SQL เนื่องจากมีประสิทธิภาพมากกว่าสำหรับSELECTคอลัมน์ที่คุณต้องการโดยเฉพาะ

ถ้าฉันต้องการSELECTทุกคอลัมน์ในตารางฉันควรใช้

SELECT * FROM TABLE

หรือ

SELECT column1, colum2, column3, etc. FROM TABLE

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

ฉันอยากรู้ว่าการปฏิบัติที่ดีที่สุดคืออะไรในกรณีนี้

UPDATE:ฉันควรระบุว่าสถานการณ์เดียวที่ฉันต้องการทำSELECT *คือเมื่อฉันเลือกข้อมูลจากตารางหนึ่งที่ฉันรู้ว่าคอลัมน์ทั้งหมดจะต้องถูกดึงเสมอแม้ว่าจะมีการเพิ่มคอลัมน์ใหม่ก็ตาม

จากคำตอบที่ฉันเห็นมานี้ยังคงเป็นความคิดที่ไม่ดีและSELECT *ไม่ควรใช้ด้วยเหตุผลทางเทคนิคมากมายที่ฉันเคยคิดถึง


4
ดูเพิ่มเติมได้ที่: stackoverflow.com/questions/208925/…
Annika Backstrom


1
ใช่มันเป็นข้อมูลส่วนใหญ่ที่ซ้ำกัน
George Stocker

คำตอบ:


168

เหตุผลหนึ่งที่การเลือกคอลัมน์ที่เฉพาะเจาะจงนั้นดีกว่าคือมันเพิ่มความน่าจะเป็นที่ SQL Server สามารถเข้าถึงข้อมูลจากดัชนีแทนที่จะสืบค้นข้อมูลตาราง

นี่คือการโพสต์ที่ผมเขียนเกี่ยวกับเรื่องนี้: เหตุผลที่แท้จริงเลือกคำสั่งมีความครอบคลุมของดัชนีที่ไม่ดี

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


3
+1 สำหรับสิ่งนี้ หากมีคอลัมน์ทั้งหมดที่อ้างอิงอยู่ในดัชนีเดียว ("ดัชนีครอบคลุม") แสดงว่าคุณมีทองคำเหลืออยู่
เอียนเนลสัน

22
นั่นไม่ใช่คำตอบสำหรับคำถามของเขา - "ถ้าฉันต้องเลือกทุกคอลัมน์ในตาราง, ... " - ในกรณีนั้น, * vs col1, .. , coln ไม่สำคัญ (แต่มันสำหรับเวลาโปรแกรมเมอร์) เนื่องจาก * สั้นกว่า!)
Matt Rogish

3
มันยังคงมีความสำคัญเนื่องจากรายการที่เลือกเป็นรูปแบบของสัญญาโดยเฉพาะอย่างยิ่งถ้า SQL อยู่ในขั้นตอนการจัดเก็บ
Eric Z Beard

4
ในขณะที่สิ่งที่จอนบอกว่าถูกต้องสมบูรณ์และเป็นจุดที่ถูกต้องมากฉันต้องเห็นพ้องว่าคำถามที่ถามเป็นเรื่องเกี่ยวกับว่าพวกเขาจะถามคอลัมน์ทั้งหมดแล้ว เนื่องจากในส่วนนี้ของคำถามประเด็นที่แท้จริงคือความเปราะบางเมื่อเผชิญกับการเปลี่ยนแปลงของสคีมา
IDisposable

1
@MattRogish คุณได้รับมันถูกต้องมีความแตกต่างของประสิทธิภาพระหว่างสองวิธีนี้ (* vsall_column_names) ในขณะที่เรามีหลายพันแถวและเราทำการเลือกด้วยดัชนี (ในส่วนคำสั่ง WHERE) ??
santosh

59

เนื่องจากข้อกำหนดของคุณว่าคุณกำลังเลือกคอลัมน์ทั้งหมดมีความแตกต่างเล็กน้อย ในขณะนี้ อย่างไรก็ตามจงตระหนักว่าสกีมาฐานข้อมูลนั้นเปลี่ยนแปลง หากคุณใช้SELECT *คุณจะได้รับคอลัมน์ใหม่เพิ่มลงในตารางแม้ว่าในทุกโอกาสรหัสของคุณไม่ได้เตรียมที่จะใช้หรือนำเสนอข้อมูลใหม่ที่ ซึ่งหมายความว่าคุณกำลังเปิดเผยระบบของคุณถึงการเปลี่ยนแปลงประสิทธิภาพและการทำงานที่ไม่คาดคิด

คุณอาจเต็มใจที่จะยกเลิกสิ่งนี้เป็นค่าใช้จ่ายเล็กน้อย แต่ทราบว่าคอลัมน์ที่คุณไม่ต้องการยังคงต้อง:

  1. อ่านจากฐานข้อมูล
  2. ส่งข้ามเครือข่าย
  3. มาร์แชลเข้าสู่กระบวนการของคุณ
  4. (สำหรับเทคโนโลยีประเภท ADO) บันทึกในหน่วยความจำภายในตารางข้อมูล
  5. ถูกละทิ้งและทิ้ง / เก็บขยะ

ไอเท็ม # 1 มีค่าใช้จ่ายแอบแฝงมากมายรวมถึงการกำจัดดัชนีที่ซ่อนเร้นทำให้การโหลดหน้าข้อมูล (และการแคชแคชของเซิร์ฟเวอร์) การล็อกแถว / หน้า / ตารางที่อาจเกิดขึ้นซึ่งอาจหลีกเลี่ยงได้

ยอดคงเหลือนี้เทียบกับการประหยัดที่เป็นไปได้ของการระบุคอลัมน์เมื่อเทียบกับ*และการประหยัดที่เป็นไปได้เท่านั้น:

  1. โปรแกรมเมอร์ไม่จำเป็นต้องกลับไปที่ SQL เพื่อเพิ่มคอลัมน์
  2. การขนส่งผ่านเครือข่ายของ SQL นั้นเล็กลง / เร็วขึ้น
  3. เวลาในการแยกวิเคราะห์ / การตรวจสอบแบบสอบถาม SQL Server
  4. แคชแผนแบบสอบถาม SQL Server

สำหรับรายการที่ 1 ความจริงก็คือคุณจะต้องเพิ่ม / เปลี่ยนรหัสเพื่อใช้คอลัมน์ใหม่ที่คุณอาจเพิ่มอยู่แล้วดังนั้นจึงเป็นการล้าง

สำหรับรายการที่ 2 ความแตกต่างนั้นแทบจะไม่พอที่จะผลักคุณไปสู่ขนาดแพ็กเก็ตหรือจำนวนแพ็กเก็ตเครือข่ายอื่น หากคุณไปถึงจุดที่เวลาในการส่งคำสั่ง SQL เป็นปัญหาที่สำคัญคุณอาจต้องลดอัตราของคำสั่งก่อน

สำหรับรายการที่ 3 ไม่มีการออมเนื่องจากการขยายตัวของสิ่งที่*ต้องเกิดขึ้นต่อไปซึ่งหมายถึงการให้คำปรึกษากับตาราง schema อยู่ดี ในความเป็นจริงการแสดงรายการคอลัมน์จะต้องเสียค่าใช้จ่ายเท่ากันเพราะจะต้องมีการตรวจสอบกับสคีมา กล่าวอีกนัยหนึ่งนี่เป็นการล้างที่สมบูรณ์

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

ดังนั้นทั้งหมดนี้เกิดขึ้นเนื่องจากวิธีการที่คุณระบุคำถามเพื่อความยืดหยุ่นของปัญหาเมื่อเผชิญกับการปรับเปลี่ยนสคีมาในที่สุด หากคุณกำลังเขียน schema นี้ลงใน ROM (เกิดขึ้น) แสดงว่า*ยอมรับได้อย่างสมบูรณ์

อย่างไรก็ตามหลักเกณฑ์ทั่วไปของฉันคือคุณควรเลือกคอลัมน์ที่คุณต้องการเท่านั้นซึ่งหมายความว่าบางครั้งมันจะดูเหมือนว่าคุณกำลังขอทั้งหมด แต่ DBA และวิวัฒนาการ schema หมายความว่าคอลัมน์ใหม่บางอย่างอาจปรากฏที่อาจส่งผลกระทบต่อแบบสอบถามอย่างมาก .

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

หากคุณสงสัยว่าทำไมสคีมาอาจเปลี่ยนแปลงได้โดยไม่ต้องเปลี่ยนรหัสให้คิดในแง่ของการบันทึกการตรวจสอบวันที่ที่มีผล / หมดอายุและสิ่งอื่น ๆ ที่คล้ายกันซึ่ง DBAs เพิ่มเข้ามาสำหรับปัญหาด้านความสอดคล้อง แหล่งที่มาของการเปลี่ยนแปลงอื่น ๆ ที่อยู่ภายใต้การดูแลคือ denormalizations สำหรับประสิทธิภาพการทำงานที่อื่นในระบบหรือเขตข้อมูลที่ผู้ใช้กำหนด


3
"ความจริงก็คือคุณจะเพิ่ม / เปลี่ยนรหัสเพื่อใช้คอลัมน์ใหม่ที่คุณอาจเพิ่มต่อไปดังนั้นมันจึงเป็นการล้าง" - เฉพาะถ้าคุณอ่านแต่ละคอลัมน์ด้วยตนเองตามชื่อในรหัสของคุณ หากคุณใช้การจับคู่อัตโนมัติกรณีนี้ไม่ได้และปัญหานี้มีความสำคัญ
Josh Noe

36

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

แอปพลิเคชันของคุณอาจแตกถ้ามีคนเพิ่มคอลัมน์ลงในตาราง โปรแกรมของคุณจะได้รับคอลัมน์ซึ่งไม่ได้คาดหวังด้วยและอาจไม่รู้วิธีการประมวลผล

นอกเหนือจากนี้หากตารางมีคอลัมน์แบบไบนารีการสืบค้นจะช้ากว่าและใช้ทรัพยากรเครือข่ายมากขึ้น


6
อ๊ะโดยใช้ * คุณกำลังเพิ่มงานพิเศษสำหรับฐานข้อมูล ตกลงนั่นเป็นเหตุผลหนึ่งที่ฉันไม่ได้คิด
Ankur

1
+1 สำหรับความเสี่ยงของการทำลาย / จับข้อผิดพลาดก่อน ฉันคิดว่าการอภิปรายเกี่ยวกับประสิทธิภาพนั้นถูกต้อง แต่ YAGNI
nailitdown

6
เซิร์ฟเวอร์ SQL ไม่จำเป็นต้องตรวจสอบหรือตรวจสอบว่า "col1" อยู่ในตารางที่ระบุหรือไม่เช่นตารางระบบคิวรี
Patrick

3
ผลการดำเนินงานที่ใหญ่ที่สุดอาจเกี่ยวข้องกับการจัดทำดัชนี หากคอลัมน์ที่คุณกำลังค้นหาอยู่เป็นส่วนหนึ่งของดัชนีที่ใช้เพื่อค้นหาข้อมูลเซิร์ฟเวอร์จะดึงข้อมูลตรงนั้นถ้าคุณเลือก * มันมักจะต้องทำสิ่งที่เรียกว่าการค้นหาบุ๊กมาร์ก สแกนเพื่อค้นหาข้อมูลพื้นฐานที่เหลือซึ่งคุณอาจไม่ต้องการ
Cobusve

3
@Patrick - จุดบน มีเหตุผลดีๆมากมายที่ควรหลีกเลี่ยง * แต่นั่นไม่ใช่หนึ่งในนั้น
Martin Smith

31

มีสี่เหตุผลใหญ่ที่select *เป็นสิ่งไม่ดีคือ:

  1. เหตุผลเชิงปฏิบัติที่สำคัญที่สุดคือบังคับให้ผู้ใช้รู้ลำดับที่คอลัมน์จะถูกส่งคืนอย่างน่าอัศจรรย์ ดีกว่าที่จะมีความชัดเจนซึ่งช่วยปกป้องคุณจากการเปลี่ยนแปลงของตารางซึ่งแบ่งออกเป็น ...

  2. หากชื่อคอลัมน์ที่คุณใช้มีการเปลี่ยนแปลงจะเป็นการดีกว่าที่จะใช้ก่อน (ณ จุดที่เรียกใช้ SQL) แทนที่จะเป็นเมื่อคุณกำลังพยายามใช้คอลัมน์ที่ไม่มีอยู่อีกต่อไป (หรือเปลี่ยนชื่อเป็นต้น )

  3. การแสดงชื่อคอลัมน์ทำให้รหัสของคุณมีเอกสารที่เป็นของตัวเองมากขึ้นและอาจอ่านได้ง่ายขึ้น

  4. หากคุณกำลังถ่ายโอนผ่านเครือข่าย (หรือแม้ว่าคุณจะไม่ได้) คอลัมน์ที่คุณไม่ต้องการก็แค่ทำให้สิ้นเปลือง


7
"เหตุผลเชิงปฏิบัติที่สำคัญที่สุดคือบังคับให้ผู้ใช้รู้ลำดับที่คอลัมน์จะถูกส่งกลับอย่างน่าอัศจรรย์" ฉันไม่เห็นว่าปัญหานี้เป็นอย่างไร ในไคลเอนต์ DB ที่ทันสมัยคุณอ่านคอลัมน์ตามชื่อไม่ใช่ลำดับ
Josh Noe

ฉันมักจะเรียกใช้ SQL ของฉันผ่านทางส่วนต่อประสาน C ดังนั้นฉันจึงไม่รู้จริงๆเลยว่าเทคโนโลยีล้ำสมัยใน "ลูกค้า DB" คืออะไร แต่ฉันคิดว่าลูกค้าประเภทที่คุณกำลังพูดถึงกำลังทำเวทมนต์ที่ไม่ได้มาตรฐานของ SQL (เช่นใน SQLite สอบถาม sqlite3_master จะคิดออกว่าจะเปลี่ยนคุณ*เป็นชุดของชื่อ.)
pkh

และอีกต่อไปจากนี้มีคนเขียนรหัสในแอปพลิเคชั่นที่ใช้ดัชนีชื่อคอลัมน์? คนส่วนใหญ่ใช้ mapper บางประเภทและแคชจำนวนมากสำหรับข้อมูลที่ได้รับอนุญาตให้ค้าง โดยส่วนตัวให้เขียนรหัสก่อนจากนั้นให้กังวลหากคุณมีปัญหาด้านประสิทธิภาพในภายหลัง
Colin Wiseman

10

การระบุรายการคอลัมน์คือ มักเป็นตัวเลือกที่ดีที่สุดเพราะใบสมัครของคุณจะไม่ได้รับผลกระทบหากมีคนเพิ่ม / แทรกคอลัมน์ลงในตาราง


7

การระบุชื่อคอลัมน์นั้นเร็วขึ้นแน่นอน - สำหรับเซิร์ฟเวอร์ แต่ถ้า

  1. ประสิทธิภาพไม่ใช่ปัญหาใหญ่ (ตัวอย่างเช่นนี่คือฐานข้อมูลเนื้อหาเว็บไซต์ที่มีหลายร้อยอาจเป็นพัน แต่ไม่ใช่ล้านแถวในแต่ละตาราง) และ
  2. งานของคุณคือการสร้างแอปพลิเคชันขนาดเล็กที่คล้ายคลึงกันจำนวนมาก (เช่นเว็บไซต์ที่มีการจัดการเนื้อหาสาธารณะ) โดยใช้เฟรมเวิร์กทั่วไปแทนที่จะสร้างแอปพลิเคชันที่ซับซ้อน และ
  3. ความยืดหยุ่นเป็นสิ่งสำคัญ (การกำหนดเองจำนวนมากของ db schema สำหรับแต่ละไซต์)

ถ้าอย่างนั้นคุณก็ควรที่จะติดกับ SELECT * ในกรอบการทำงานของเราการใช้งาน SELECT * อย่างหนักทำให้เราสามารถนำเสนอฟิลด์เนื้อหาที่มีการจัดการเว็บไซต์ใหม่ลงในตารางซึ่งให้ประโยชน์ทั้งหมดของ CMS (การกำหนดเวอร์ชันเวิร์กโฟลว์ / การอนุมัติ ฯลฯ ) ในขณะที่แตะรหัสที่ สองสามคะแนนแทนที่จะเป็นสองสามคะแนน

ฉันรู้ว่าปรมาจารย์ DB จะเกลียดฉันในเรื่องนี้ - ไปข้างหน้าลงคะแนนให้ฉัน - แต่ในโลกของฉันเวลาของนักพัฒนานั้นหายากและรอบการทำงานของ CPU นั้นมากมายดังนั้นฉันจึงปรับสิ่งที่ฉันอนุรักษ์ไว้และสิ่งที่ฉันเสียไป


1
นอกจากนี้ยังทำให้ ORMs ใช้งานง่ายขึ้นมาก เมื่อมีการสร้างแบบสอบถามโดยการส่งวัตถุสร้างแบบสอบถามไปรอบ ๆ หนึ่งก็ไม่จำเป็นต้องทราบว่าคอลัมน์ใดถูกต้องโดยส่วนอื่น ๆ ของรหัส (ตรวจสอบสิทธิ์สิ่งที่คุณมี) ดังนั้นเพื่อ จำกัด คอลัมน์หนึ่งจะต้องตรวจสอบทุกครั้งที่ต้องการเขียนแบบสอบถาม นี่ไม่มีจุดหมาย IMO เมื่อข้อความค้นหากลายเป็นช้า (บันทึก!) คุณสามารถปรับปรุงข้อความค้นหาได้
bytepusher

6

SELECT * เป็นแนวทางปฏิบัติที่ไม่ดีแม้ว่าจะไม่มีการส่งแบบสอบถามผ่านเครือข่าย

  1. การเลือกข้อมูลมากกว่าที่คุณต้องการทำให้แบบสอบถามมีประสิทธิภาพน้อยลง - เซิร์ฟเวอร์ต้องอ่านและถ่ายโอนข้อมูลเพิ่มเติมดังนั้นจึงต้องใช้เวลาและสร้างภาระที่ไม่จำเป็นในระบบ (ไม่เฉพาะเครือข่ายตามที่คนอื่นพูดถึง แต่ยังดิสก์ CPU ฯลฯ ) นอกจากนี้เซิร์ฟเวอร์ไม่สามารถปรับให้เหมาะสมของแบบสอบถามได้เช่นกัน (ตัวอย่างเช่นใช้การครอบคลุมดัชนีสำหรับแบบสอบถาม)
  2. หลังจากเวลาหนึ่งโครงสร้างตารางของคุณอาจเปลี่ยนไปดังนั้น SELECT * จะส่งคืนชุดคอลัมน์ที่แตกต่างกัน ดังนั้นแอปพลิเคชันของคุณอาจได้รับชุดข้อมูลของโครงสร้างที่ไม่คาดคิดและทำลายบางส่วนของดาวน์สตรีม การระบุคอลัมน์อย่างชัดเจนรับประกันได้ว่าคุณจะได้รับชุดข้อมูลของโครงสร้างที่รู้จักหรือได้รับข้อผิดพลาดที่ชัดเจนในระดับฐานข้อมูล (เช่น 'ไม่พบคอลัมน์')

แน่นอนว่าทั้งหมดนี้ไม่สำคัญมากนักสำหรับระบบขนาดเล็กและเรียบง่าย


4

ประสิทธิภาพอย่างชาญฉลาด SELECT ที่มีคอลัมน์เฉพาะสามารถทำงานได้เร็วขึ้น (ไม่จำเป็นต้องอ่านข้อมูลทั้งหมด) หากแบบสอบถามของคุณใช้คอลัมน์ทั้งหมดจริงๆแล้ว SELECT ยังมีพารามิเตอร์ที่ชัดเจน ความแตกต่างของความเร็วจะไม่สามารถสังเกตเห็นได้โดยทั่วไปและใกล้กับเวลาคงที่ วันหนึ่งสคีมาของคุณจะเปลี่ยนไปและนี่เป็นการประกันที่ดีเพื่อป้องกันปัญหาอันเนื่องมาจากสิ่งนี้


คุณผิดเกี่ยวกับสิ่งที่สังเกตไม่ได้ตั้งแต่การตรวจสอบที่ฉันทำกับฐานข้อมูลหลาย ๆ ฉบับมันชัดเจนว่าการเลือกแต่ละคอลัมน์แม้ว่าทั้งหมดนั้นจะเร็วกว่ามาก ในบางกรณีมันเร็วกว่าสามเท่า
shahar eldad

4

เหตุผลที่ดีมากมายตอบที่นี่จนถึงนี่เป็นอีกหนึ่งที่ไม่ได้กล่าวถึง

การตั้งชื่อคอลัมน์อย่างชัดเจนจะช่วยคุณในการดูแลรักษาถนน ในบางจุดคุณจะต้องทำการเปลี่ยนแปลงหรือแก้ไขปัญหาและพบว่าตัวเองถามว่า "คอลัมน์ไหนที่ใช้ heck"

หากคุณมีชื่ออยู่ในรายการอย่างชัดเจนจากนั้นการค้นหาการอ้างอิงทั้งหมดไปยังคอลัมน์นั้นผ่านขั้นตอนมุมมองและอื่น ๆ ที่คุณเก็บไว้นั้นเป็นเรื่องง่าย เพียงทิ้งสคริปต์ CREATE สำหรับ DB schema ของคุณแล้วค้นหาข้อความ


3

กำหนดคอลัมน์อย่างแน่นอนเนื่องจาก SQL Server จะไม่ต้องทำการค้นหาในคอลัมน์เพื่อดึงพวกเขา หากคุณกำหนดคอลัมน์ดังนั้น SQL สามารถข้ามขั้นตอนนั้นได้


นี่คือ: 1) ไม่เกี่ยวข้องเนื่องจาก SQL Server ต้องอ้างอิง schema ของตารางด้วยวิธีใดวิธีหนึ่ง (เพื่อตรวจสอบชื่อคอลัมน์หรือค้นหาชื่อคอลัมน์ที่ถูกต้องที่รู้จัก) 2) ไม่เกี่ยวข้องกับคำถามที่ถามซึ่งมีการอ้างอิงคอลัมน์ทั้งหมด ปัญหาเดียวที่ถูกถามคือความเปราะบางที่มีการเปลี่ยนแปลงสคี
IDisposable

ลดลงเนื่องจากต้องตรวจสอบความถูกต้องของคอลัมน์
John Gibb

3

มันจะดีกว่าเสมอในการระบุคอลัมน์ที่คุณต้องการถ้าคุณคิดถึงมันครั้งเดียว SQL ไม่ต้องคิดว่า "wtf is *" ทุกครั้งที่คุณสืบค้น ยิ่งไปกว่านั้นบางคนอาจเพิ่มคอลัมน์ในตารางที่คุณไม่ต้องการใช้ในการค้นหาและคุณจะดีขึ้นในกรณีนั้นด้วยการระบุคอลัมน์ทั้งหมดของคุณ


1
สิ่งนี้ไม่เป็นความจริง: เซิร์ฟเวอร์ SQL จะต้องแยกวิเคราะห์แต่ละคอลัมน์และดูว่ามีอยู่ในแคตตาล็อกหรือไม่ในขณะที่รู้ว่า "*" ทำ (และใช่, * จะถูกขยายเป็นคอลัมน์ทั้งหมด) ไม่ว่าจะด้วยวิธีใดก็ตามเป็นเรื่องง่ายสำหรับ DBMS ที่จะทำอย่างใดอย่างหนึ่ง (เว้นแต่คุณจะมี 24,000 คอลัมน์) ดังนั้นฉันจึงเดิมพันเหมือนกันทั้งทาง
Matt Rogish

ฉันคิดว่าจุดที่ดีกว่าที่หลายคนขาดหายไปและน่าเสียดายที่คำตอบนี้ให้ที่อยู่ที่สองเท่านั้นคือหากการเปลี่ยนสคีมา / ตารางเกิดขึ้น (เช่นเพิ่มคอลัมน์ใหม่) จะไม่ทำให้สิ่งแตกหัก
Sean Hanley

1
เป็นการล้างอย่างสมบูรณ์เมื่อค้นหาคอลัมน์สำหรับการขยาย * เหมือนกับการตรวจสอบความถูกต้องของชื่อคอลัมน์ที่ให้ไว้
IDisposable

3

ปัญหาของ "select *" คือความเป็นไปได้ในการนำข้อมูลที่คุณไม่ต้องการ ในระหว่างการสืบค้นฐานข้อมูลจริงคอลัมน์ที่เลือกไม่ได้เพิ่มในการคำนวณ สิ่งที่ "หนักหน่วง" จริงๆแล้วคือการรับส่งข้อมูลกลับไปยังไคลเอนต์ของคุณและคอลัมน์ใด ๆ ที่คุณไม่ต้องการจริงๆคือการสิ้นเปลืองแบนด์วิดท์ของเครือข่ายและเพิ่มเวลาที่คุณรอให้คุณสอบถามเพื่อกลับมา

แม้ว่าคุณจะใช้คอลัมน์ทั้งหมดที่นำมาจาก "select * ... " นั่นเป็นเพียงแค่ตอนนี้ หากในอนาคตคุณเปลี่ยนเค้าโครงตาราง / มุมมองและเพิ่มคอลัมน์เพิ่มเติมคุณจะเริ่มนำสิ่งเหล่านี้มาใช้ในการเลือกของคุณแม้ว่าคุณจะไม่ต้องการก็ตาม

อีกจุดหนึ่งที่คำสั่ง "select *" ไม่ดีอยู่ที่การสร้างมุมมอง หากคุณสร้างมุมมองโดยใช้ "select *" แล้วเพิ่มคอลัมน์ลงในตารางของคุณนิยามมุมมองและข้อมูลที่ส่งคืนจะไม่ตรงกันและคุณจะต้องคอมไพล์มุมมองของคุณอีกครั้งเพื่อให้ทำงานได้อีกครั้ง

ฉันรู้ว่าการเขียน "select *" เป็นการดึงดูดเพราะฉันไม่ชอบระบุเขตข้อมูลทั้งหมดด้วยตนเองในแบบสอบถามของฉัน แต่เมื่อระบบของคุณเริ่มมีวิวัฒนาการคุณจะเห็นว่ามันคุ้มค่าที่จะใช้เวลาพิเศษนี้ / ความพยายามในการระบุฟิลด์แทนที่จะใช้เวลามากขึ้นและพยายามกำจัดข้อบกพร่องในมุมมองของคุณหรือเพิ่มประสิทธิภาพแอปของคุณ


จุดชมวิวมีความสำคัญมาก ไม่เพียงคุณจะไม่ได้รับคอลัมน์ทั้งหมดหากคุณเพิ่มคอลัมน์ลงในตาราง (แม้จะมีสิ่งที่ * จะทำให้คุณคิด) แต่พวกเขาอาจไม่ตรงกับเค้าโครงที่แท้จริงของตาราง
Euro Micelli

3

ในขณะที่การแสดงรายการคอลัมน์อย่างชัดเจนนั้นดีต่อประสิทธิภาพ แต่อย่าบ้า

ดังนั้นหากคุณใช้ข้อมูลทั้งหมดให้ลองเลือก * เพื่อความเรียบง่าย (ลองนึกภาพว่ามีหลายคอลัมน์และทำแบบสอบถาม JOIN ... อาจแย่มาก) จากนั้น - วัด เปรียบเทียบกับการสืบค้นด้วยชื่อคอลัมน์ที่ระบุไว้อย่างชัดเจน

อย่าคาดเดาเกี่ยวกับประสิทธิภาพ วัดเลย!

รายการที่ชัดเจนช่วยได้มากที่สุดเมื่อคุณมีคอลัมน์ที่มีข้อมูลขนาดใหญ่ (เช่นเนื้อความของโพสต์หรือบทความ) และไม่ต้องการในการสืบค้น จากนั้นโดยไม่ส่งคืนในเซิร์ฟเวอร์ฐานข้อมูลคำตอบของคุณสามารถประหยัดเวลาแบนด์วิดท์และปริมาณงานของดิสก์ ผลการสืบค้นของคุณจะเล็กลงซึ่งเหมาะสำหรับแคชแบบสอบถามใด ๆ


3

คุณควรเลือกเฉพาะฟิลด์ที่คุณต้องการและเฉพาะหมายเลขที่ต้องการเช่น

SELECT Field1, Field2 FROM SomeTable WHERE --(constraints)

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


"เซิร์ฟเวอร์จะต้องสร้างแผนการดำเนินการทุกครั้งที่มีการเรียกใช้คิวรีแบบไดนามิก" ซึ่งฉันถือว่าการสืบค้นช้าลง ขอบคุณ
Ankur

ปัญหาประสิทธิภาพของการใช้ sql แบบไดนามิกอาจจะรับรู้ได้เฉพาะในสถานการณ์โหลดสูงมาก SQL Server ค่อนข้างดีในการจัดการแผนแบบสอบถามอย่างมีประสิทธิภาพ
Matthew Abbott

2

การเลือกมีประสิทธิภาพเท่าเทียมกัน (ในแง่ของความเร็ว) หากคุณใช้ * หรือคอลัมน์

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

สิ่งที่สำคัญในแง่ของประสิทธิภาพการทำงานคือแผนการ excecution ซึ่งจะขึ้นอยู่กับข้อของคุณและจำนวนของการเข้าร่วมออกนอกเข้าร่วม ฯลฯ ...

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


2

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

ซอฟต์แวร์ไคลเอ็นต์ของคุณไม่ควรขึ้นอยู่กับลำดับของฟิลด์ที่ส่งคืนดังนั้นจึงเป็นเรื่องไร้สาระเช่นกัน

และเป็นไปได้ (แต่ไม่น่าเป็นไปได้) ที่คุณต้องทำให้ทุกฟิลด์ใช้ * เนื่องจากคุณยังไม่รู้ว่ามีฟิลด์ใดบ้าง (คิดว่าโครงสร้างฐานข้อมูลแบบไดนามิกมาก)

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

ดังนั้นกฎควรเป็น: หากคุณต้องการฟิลด์ทั้งหมดใช้ * หากคุณต้องการเพียงชุดย่อยให้ตั้งชื่อให้ชัดเจน


2

ผลลัพธ์มีขนาดใหญ่เกินไป มันช้าในการสร้างและส่งผลลัพธ์จากเอนจิน SQL ไปยังไคลเอนต์

ฝั่งไคลเอ็นต์ซึ่งเป็นสภาพแวดล้อมการเขียนโปรแกรมทั่วไปไม่ใช่และไม่ควรได้รับการออกแบบมาเพื่อกรองและประมวลผลผลลัพธ์ (เช่น WHERE clause, ORDER clause clause) เนื่องจากจำนวนของแถวอาจมีขนาดใหญ่ (เช่นหลายสิบล้านแถว)


ดังนั้นหากคุณต้องการใช้คอลัมน์ที่แตกต่างกันจริง ๆ มันก็ใช้ได้ ... และถ้าฐานข้อมูลและแอพของคุณกำลังนั่งอยู่บนเซิร์ฟเวอร์เดียวกันอีกครั้ง
Ankur

@Ankur: แม้แต่บนเซิร์ฟเวอร์เดียวกันก็มีค่าใช้จ่ายในการส่งข้อมูลผ่านส่วนต่อประสานฐานข้อมูล
kennytm

2

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


1

ขึ้นอยู่กับรุ่นของเซิร์ฟเวอร์ฐานข้อมูลของคุณ แต่ SQL เวอร์ชันที่ทันสมัยสามารถแคชแผนด้วยวิธีใดวิธีหนึ่ง ฉันจะบอกว่าอะไรก็ตามที่สามารถบำรุงรักษาได้มากที่สุดด้วยรหัสการเข้าถึงข้อมูลของคุณ


1

เหตุผลหนึ่งที่ควรปฏิบัติให้ดีที่สุดคือการวิเคราะห์ว่าคอลัมน์ใดที่คุณต้องการเนื่องจากการเปลี่ยนแปลงในอนาคตของโครงสร้างตาราง

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

สำหรับสิ่งที่เร็วกว่าฉันจะรอคนอื่น ๆ เพื่อความเชี่ยวชาญของพวกเขา


1

เช่นเดียวกับปัญหาส่วนใหญ่ขึ้นอยู่กับสิ่งที่คุณต้องการบรรลุ หากคุณต้องการสร้างตาราง db ที่จะอนุญาตให้คอลัมน์ทั้งหมดในตารางใด ๆ "เลือก *" เป็นคำตอบ อย่างไรก็ตามหากคุณต้องการเพียงคอลัมน์บางคอลัมน์เท่านั้นและการเพิ่มหรือลบคอลัมน์จากคิวรีนั้นจะเกิดขึ้นไม่บ่อยนักให้ระบุแต่ละคอลัมน์

นอกจากนี้ยังขึ้นอยู่กับปริมาณข้อมูลที่คุณต้องการถ่ายโอนจากเซิร์ฟเวอร์ หากหนึ่งในคอลัมน์นั้นถูกกำหนดให้เป็นบันทึก, กราฟิก, blob ฯลฯ และคุณไม่ต้องการคอลัมน์นั้นคุณควรที่จะไม่ใช้ "เลือก *" มิฉะนั้นคุณจะได้รับข้อมูลทั้งหมดที่คุณไม่ต้องการ ต้องการและประสิทธิภาพการทำงานของคุณอาจประสบ


1

เพื่อเพิ่มสิ่งที่ทุกคนพูดถ้าคอลัมน์ทั้งหมดที่คุณเลือกรวมอยู่ในดัชนีชุดผลลัพธ์ของคุณจะถูกดึงจากดัชนีแทนที่จะค้นหาข้อมูลเพิ่มเติมจาก SQL



1

สิ่งที่ทุกคนข้างต้นพูดบวก:

หากคุณกำลังพยายามอ่านรหัสที่สามารถบำรุงรักษาได้ให้ทำดังนี้:

เลือก foo, bar จากวิดเจ็ต;

สามารถอ่านได้ทันทีและแสดงเจตนา ถ้าคุณโทรออกคุณจะรู้ว่าคุณได้รับอะไรกลับมา หากวิดเจ็ตมีเพียงคอลัมน์ foo และบาร์เท่านั้นให้เลือก * หมายความว่าคุณยังต้องคำนึงถึงสิ่งที่คุณได้รับกลับมายืนยันว่าคำสั่งซื้อนั้นถูกแมปอย่างถูกต้อง ฯลฯ อย่างไรก็ตามหากวิดเจ็ตมีคอลัมน์มากกว่า แต่คุณสนใจ foo เท่านั้น และแถบจากนั้นรหัสของคุณจะยุ่งเมื่อคุณค้นหาสัญลักษณ์ตัวแทนจากนั้นใช้เฉพาะสิ่งที่ส่งคืน


1

และจำไว้ว่าถ้าคุณมีการรวมภายในโดยนิยามคุณไม่ต้องการคอลัมน์ทั้งหมดเนื่องจากข้อมูลในคอลัมน์การรวมซ้ำแล้วซ้ำอีก

ไม่เหมือนกับการแสดงรายการคอลัมน์ในเซิร์ฟเวอร์ SQl ยากหรือใช้เวลานาน คุณเพียงแค่ลากพวกเขาไปจากเบราว์เซอร์วัตถุ (คุณสามารถรับทั้งหมดในครั้งเดียวโดยการลากจากคอลัมน์คำ) เพื่อให้ประสิทธิภาพการทำงานของระบบของคุณลดลงอย่างถาวร (เพราะสิ่งนี้สามารถลดการใช้ดัชนีและเนื่องจากการส่งข้อมูลที่ไม่จำเป็นผ่านเครือข่ายมีค่าใช้จ่ายสูง) และทำให้มีโอกาสมากขึ้นที่คุณจะมีปัญหาที่ไม่คาดคิดเมื่อมีการเปลี่ยนแปลงฐานข้อมูล คุณไม่ต้องการให้ผู้ใช้เห็นตัวอย่าง) เพียงเพื่อประหยัดเวลาในการพัฒนาน้อยกว่าหนึ่งนาทีก็คือการมองเห็นในระยะสั้นและไม่เป็นมืออาชีพ


1

ประสิทธิภาพการทำงานที่ชาญฉลาดฉันได้เห็นความคิดเห็นที่ทั้งสองเท่ากัน แต่แง่มุมการใช้งานมีบางอย่างของ + และ

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

ในทางกลับกันถ้าคุณใช้ (เลือก col1, col2, .. ) และหากตารางมีการเปลี่ยนแปลงและเพิ่มเขตข้อมูลใหม่และหากจำเป็นต้องมีเขตข้อมูลเหล่านั้นในชุดผลลัพธ์คุณจะต้องแก้ไขแบบสอบถามแบบใช้เลือกข้อมูลของคุณเสมอหลังจากการเปลี่ยนแปลงตาราง

แต่ฉันขอแนะนำให้ใช้เลือก col1, col2, ... ในข้อความค้นหาของคุณและแก้ไขแบบสอบถามหากตารางได้รับการแก้ไขในภายหลัง ...


0

กำหนดคอลัมน์ที่คุณต้องการเลือกอย่างแน่นอนทุกครั้ง ไม่มีเหตุผลที่จะไม่ทำและการปรับปรุงประสิทธิภาพก็คุ้มค่า

พวกเขาไม่ควรให้ตัวเลือก "SELECT *"


0

หากคุณต้องการทุกคอลัมน์ให้ใช้ SELECT * แต่โปรดจำไว้ว่าคำสั่งซื้ออาจมีการเปลี่ยนแปลงดังนั้นเมื่อคุณใช้ผลลัพธ์ที่เข้าถึงพวกเขาตามชื่อไม่ใช่ตามดัชนี

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


0

ในแง่ของประสิทธิภาพการดำเนินการฉันไม่ได้ตระหนักถึงความแตกต่างที่สำคัญ แต่เพื่อประสิทธิภาพของโปรแกรมเมอร์ฉันจะเขียนชื่อของฟิลด์เพราะ

  • คุณรู้คำสั่งถ้าคุณต้องการทำดัชนีตามหมายเลขหรือถ้าคนขับของคุณมีพฤติกรรมตลก ๆ เกี่ยวกับค่าหยดและคุณต้องมีลำดับที่แน่นอน
  • คุณอ่านเฉพาะฟิลด์ที่คุณต้องการถ้าคุณควรเพิ่มฟิลด์เพิ่มเติม
  • คุณได้รับข้อผิดพลาด sql ถ้าคุณสะกดคำผิดหรือเปลี่ยนชื่อเขตข้อมูลไม่ใช่ค่าว่างจากชุดระเบียน / แถว
  • คุณสามารถอ่านสิ่งที่เกิดขึ้นได้ดีขึ้น

0

เฮ้จงปฏิบัติได้ ใช้ select * เมื่อทำต้นแบบและเลือกคอลัมน์เฉพาะเมื่อนำไปใช้และปรับใช้ จากมุมมองแผนปฏิบัติการทั้งสองค่อนข้างเหมือนกันในระบบที่ทันสมัย อย่างไรก็ตามการเลือกคอลัมน์เฉพาะนั้น จำกัด จำนวนข้อมูลที่จะต้องดึงจากดิสก์เก็บไว้ในหน่วยความจำและส่งผ่านเครือข่าย

ในที่สุดแผนการที่ดีที่สุดคือการเลือกคอลัมน์เฉพาะ

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