먼저 결론부터
SELECT *는 항상 느린 문법이 아닙니다. 모든 컬럼이 실제로 필요하다면 컬럼 이름을 나열해도 읽어야 할 데이터는 같습니다. 일부 컬럼만 쓰는데 넓은 row나 큰 text·JSON·bytea 값까지 가져올 때 tuple 처리, TOAST 접근, 출력 변환과 client 전송 비용이 불필요하게 늘 수 있습니다.
Index Only Scan과의 관계
명시한 컬럼이 index에 모두 들어 있으면 index-only scan 후보가 될 수 있지만 SELECT *가 index 밖 컬럼까지 요구하면 그 조건을 잃습니다. index가 컬럼을 모두 담아도 visibility map의 all-visible bit가 없는 heap page는 가시성 확인을 위해 방문하므로 plan 이름만 보고 heap 접근이 0이라고 단정하지 않습니다.
판단 기준
작은 table의 한 행을 조회하거나 모든 컬럼을 실제로 사용하는 경우 차이가 noise보다 작을 수 있습니다. 같은 filter와 parameter에서 row 수, width, scan, Heap Fetches, shared buffer, serialization과 실제 응답 byte를 확인합니다. 명시적 컬럼은 schema 변경 때 응답 shape를 안정시키는 성능 외 장점도 따로 판단합니다.