* 사용을 정당화 할 수 있습니까?
나는 항상 개발자들에게 SELECT *
악하고 전염병처럼 피해야한다고 설교했습니다 .
정당화 될 수있는 경우가 있습니까?
나는 COUNT(*)
대부분의 옵티마이 저가 알아낼 수있는 것에 대해 말하는 것이 아닙니다 .
편집하다
나는 프로덕션 코드에 대해 이야기하고 있습니다.
그리고 내가 본 나쁜 사례 중 하나 select *
는 저장 프로 시저에서 사용 ADO
하고 반환 된 레코드를 반복 하는 데 사용되는 레거시 ASP 응용 프로그램 이지만 인덱스별로 열을 얻었습니다. 필드 목록의 끝이 아닌 다른 곳에 새 필드가 추가되었을 때 어떤 일이 발생했는지 상상할 수 있습니다.
*
감사 트리거에서 사용하는 것이 매우 기쁩니다 .
이 경우 기본 테이블에 추가 열이 추가되면 오류가 발생하여 감사 트리거 및 / 또는 감사 테이블 구조에서이를 처리하는 것을 잊을 수 없기 때문에 실제로 이점을 입증 할 수 있습니다.
( dotjoe 처럼 ) 파생 테이블과 열 테이블 표현식에서도 사용하는 것이 기쁩니다. 나는 습관적으로 그것을 반대로한다.
WITH t
AS (SELECT *,
ROW_NUMBER() OVER (ORDER BY a) AS RN
FROM foo)
SELECT a,
b,
c,
RN
FROM t;
저는 대부분 SQL Server에 익숙하며 적어도 옵티마이 저는 열만 a,b,c
필요하고 *
내부 테이블 식에서 사용 하면 불필요한 열을 검색하고 삭제하는 불필요한 오버 헤드가 발생하지 않는다는 것을 인식하는 데 문제 가 없습니다.
원칙적 SELECT *
으로는 SELECT
피해야 할 뷰 의 최종일뿐만 아니라 뷰에서도 괜찮아 야하지만 SQL Server에서는 기본 테이블이 변경 될 때 자동으로 업데이트되지 않는 뷰에 대한 열 메타 데이터를 저장하므로 문제가 발생할 수 있습니다. 를 사용 하면이 메타 데이터를 업데이트하기 위해 실행 *
하지 않는 한 혼란스럽고 잘못된 결과 가 발생할 수 있습니다 sp_refreshview
.
SELECT *가 최적의 솔루션 인 많은 시나리오가 있습니다. 작업중인 데이터를 파악하기 위해 Management Studio에서 임시 쿼리를 실행합니다. 새 스키마로 작업 한 것이 처음이기 때문에 아직 열 이름을 모르는 테이블을 쿼리합니다. 일회성 마이그레이션 또는 데이터 내보내기를 수행하기 위해 일회용 빠르고 더러운 도구를 빌드합니다.
"적절한"개발에서는이를 피해야한다는 데 동의합니다.하지만 "적절한"개발이 반드시 비즈니스 문제에 대한 최적의 솔루션이 아닌 시나리오가 많이 있습니다. 규칙과 모범 사례는 규칙을 어길 때 알고 있다면 훌륭합니다. :)
CTE로 작업 할 때 프로덕션에서 사용할 것입니다. 그러나이 경우 select *
CTE에 이미 열을 지정했기 때문에 실제로는 아닙니다 . 최종 선택에서 다시 지정하고 싶지 않습니다.
with t as (
select a, b, c from foo
)
select t.* from t;
라이브 코드에 대해 이야기하고 있다면 제가 생각할 수있는 것은 없습니다.
열을 추가하는 것이 더 쉽게 개발되도록 만든다고 말하는 사람들은 (따라서 자동으로 반환되고 저장 프로 시저를 변경하지 않고 사용할 수 있음) 최적의 코드 / SQL 작성에 대해 알지 못합니다.
재사용되지 않는 임시 쿼리를 작성할 때만 사용합니다 (테이블 구조 찾기, 열 이름이 확실하지 않을 때 일부 데이터 가져 오기).
절 select *
에서 사용 하는 exists
것이 적절 하다고 생각합니다 .
select some_field from some_table
where exists
(select * from related_table [join condition...])
어떤 사람들은 사용하려면 select 1
이 경우에, 그러나 우아한 아니다, 그것은 구입하지 않는 어떤 (초기 최적화 다시 파업) 성능 향상.
프로덕션 코드에서는 100 % 동의하는 경향이 있습니다.
그러나 *는 임시 쿼리를 수행 할 때 그 존재를 정당화하는 것 이상이라고 생각합니다.
질문에 대한 답변을 많이 받았지만 듣고 싶은 내용을 무시하지 않는 모든 것을 무시하는 것 같습니다. 그래도 세 번째 (지금까지) 시간입니다. 때때로 병목 현상 이 없습니다. 때로는 성능이 좋은 것보다 훨씬 낫습니다. 때로는 테이블이 유동적이며 모든 SELECT 쿼리를 수정하면 관리 할 수있는 불일치가 하나 더 있습니다. 때로는 불가능한 일정에 맞춰 배송해야하는데 이것이 마지막으로 생각해야 할 사항입니다.
총알 시간에 살고 있다면 모든 열 이름을 입력하십시오. 하지만 왜 거기서 멈추나요? 스키마가없는 dbms로 앱을 다시 작성하십시오. 지옥, 어셈블리에 자신의 dbms를 작성하십시오 . 그것은 정말로 그들을 보여줄 것입니다.
그리고 select *를 사용하고 조인이있는 경우 하나 이상의 필드가 두 번 전송됩니다 (조인 필드). 이것은 아무런 이유없이 데이터베이스 리소스와 네트워크 리소스를 낭비합니다.
도구로서 나는 쿼리에서 무엇을 얻을 수 있는지에 대한 내 기억을 빠르게 새로 고치기 위해 그것을 사용합니다. 생산 수준 쿼리 자체로 .. 절대 안돼.
phpmyadmin과 같은 데이터베이스를 다루는 응용 프로그램을 만들 때 전체 테이블을 표시 할 페이지에있는 경우 사용하는 SELECT *
것이 정당화 될 수 있습니다.
내가 생각할 수있는 유일한 것은 모든 데이터베이스에 대해 실행되도록 작성되는 유틸리티 또는 SQL 도구 응용 프로그램을 개발할 때입니다. 여기에서도 시스템 테이블을 쿼리하여 테이블 구조를 얻은 다음 필요한 쿼리를 작성하는 경향이 있습니다.
최근에 우리 팀이 사용한 곳 SELECT *
이 있었는데 괜찮다고 생각합니다. 다른 데이터베이스에 대한 파사드로 존재하는 데이터베이스 (DB_Data라고 함)가 있으므로 기본적으로 테이블에 대한 뷰로 구성됩니다. 다른 데이터베이스. 뷰를 생성 할 때 실제로 열 목록을 생성하지만 DB_Data 데이터베이스에는 일반 조회 테이블에 행이 추가 될 때 자동으로 생성되는 뷰 세트가 하나 있습니다 (이 디자인은 여기에 오기 전에 적용되었습니다). 이 프로세스에 의해 DB_Data에 뷰가 생성 될 때 파사드에 다른 뷰가 자동으로 생성되도록 DDL 트리거를 작성했습니다. 뷰는 항상 DB_Data의 뷰와 정확히 일치하도록 생성되고 항상 새로 고쳐지고 동기화 상태로 유지되기 SELECT *
때문에 단순성을 위해 사용 했습니다.
I wouldn't be surprised if most developers went their entire career without having a legitimate use for SELECT *
in production code though.
I've used select * to query tables optimized for reading (denormalized, flat data). Very advantageous since the purpose of the tables were simply to support various views in the application.
How else do the developers of phpmyadmin
ensure they are displaying all the fields of your DB tables?
It is conceivable you'd want to design your DB and application so that you can add a column to a table without needing to rewrite your application. If your application at least checks column names it can safely use SELECT *
and treat additional columns with some appropriate default action. Sure the app could consult system catalogs (or app-specific catalogs) for column information, but in some circumstances SELECT *
is syntactic sugar for doing that.
There are obvious risks to this, however, and adding the required logic to the app to make it reliable could well simply mean replicating the DB's query checks in a less suitable medium. I am not going to speculate on how the costs and benefits trade off in real life.
In practice, I stick to SELECT *
for 3 cases (some mentioned in other answers:
- As an ad-hoc query, entered in a SQL GUI or command line.
- As the contents of an
EXISTS
predicate. - In an application that dealt with generic tables without needing to know what they mean (e.g. a dumper, or differ).
Yes, but only in situations where the intention is to actually get all the columns from a table not because you want all the columns that a table currently has.
For example, in one system that I worked on we had UDFs (User Defined Fields) where the user could pick the fields they wanted on the report, the order as well as filtering. When building a result set it made more sense to simply "select *" from the temporary tables that I was building instead of having to keep track of which columns were active.
I have several times needed to display data from a table whose column names were unknown. So I did
SELECT *
and got the column names at run time.I was handed a legacy app where a table had 200 columns and a view had 300. The risk exposure from
SELECT *
would have been no worse than from listing all 300 columns explicitly.
Depends on the context of the production software.
If you are writing a simple data access layer for a table management tool where the user will be selecting tables and viewing results in a grid, then it would seem *SELECT ** is fine.
In other words, if you choose to handle "selection of fields" through some other means (as in automatic or user-specified filters after retrieving the resultset) then it seems just fine.
If on the other hand we are talking about some sort of enterprise software with business rules, a defined schema, etc. ... then I agree that *SELECT ** is a bad idea.
EDIT: Oh and when the source table is a stored procedure for a trigger or view, "*SELECT **" should be fine because you're managing the resultset through other means (the view's definition or the stored proc's resultset).
Select *
in production code is justifiable any time that:
- it isn't a performance bottleneck
- development time is critical
Why would I want the overhead of going back and having to worry about changing the relevant stored procedures, every time I add a field to the table?
Why would I even want to have to think about whether or not I've selected the right fields, when the vast majority of the time I want most of them anyway, and the vast majority of the few times I don't, something else is the bottleneck?
If I have a specific performance issue then I'll go back and fix that. Otherwise in my environment, it's just premature (and expensive) optimisation that I can do without.
Edit.. following the discussion, I guess I'd add to this:
... and where people haven't done other undesirable things like tried to access columns(i), which could break in other situations anyway :)
I know I'm very late to the party but I'll chip in that I use select * whenever I know that I'll always want all columns regardless of the column names. This may be a rather fringe case but in data warehousing, I might want to stage an entire table from a 3rd party app. My standard process for this is to drop the staging table and run
select *
into staging.aTable
from remotedb.dbo.aTable
Yes, if the schema on the remote table changes, downstream dependencies may throw errors but that's going to happen regardless.
If you want to find all the columns and want order, you can do the following (at least if you use MySQL):
SHOW COLUMNS FROM mytable FROM mydb;
(1)
You can see every relevant information about all your fields. You can prevent problems with types and you can know for sure all the column names. This command is very quick, because you just ask for the structure of the table. From the results you will select all the name and will build a string like this:
"select " + fieldNames[0] + ", fieldNames[1]" + ", fieldNames[2] from mytable". (2)
If you don't want to run two separate MySQL commands because a MySQL command is expensive, you can include (1) and (2) into a stored procedure which will have the results as an OUT parameter, that way you will just call a stored procedure and every command and data generation will happen at the database server.
참고URL : https://stackoverflow.com/questions/3635781/can-select-usage-ever-be-justified
'developer tip' 카테고리의 다른 글
Swift의 UICollectionView의 셀 registerClass (0) | 2020.11.26 |
---|---|
셸 스크립트를 사용하여 도커 컨테이너 내에서 스크립트 실행 (0) | 2020.11.26 |
Virtualenv로 pip를 통해 설치할 수 없습니다. (0) | 2020.11.26 |
moq 객체 반환 메서드, null 객체를 반환해야 함 (0) | 2020.11.26 |
최적화가 활성화 된 상태에서이 코드가 6.5 배 더 느린 이유는 무엇입니까? (0) | 2020.11.25 |