[SQL] 사용하여 하위 쿼리 * 1를 존재하거나 존재
SQL사용하여 하위 쿼리 * 1를 존재하거나 존재
나는이 같은 검사를 EXISTS 작성하는 데 사용 :
IF EXISTS (SELECT * FROM TABLE WHERE Columns=@Filters)
BEGIN
UPDATE TABLE SET ColumnsX=ValuesX WHERE Where Columns=@Filters
END
이전의 삶에서 DBA 년대 중 하나는 내가이 EXISTS 절 수행 할 때, 사용하는 대신 SELECT의 1을 선택하는 것이 나에게 말했다 *
IF EXISTS (SELECT 1 FROM TABLE WHERE Columns=@Filters)
BEGIN
UPDATE TABLE SET ColumnsX=ValuesX WHERE Columns=@Filters
END
이 정말 달라 지나요?
해결법
-
==============================
1.아니, SQL 서버는 스마트이며 존재를 위해 사용되는 알고 있으며, 시스템에 데이터를 반환합니다.
아니, SQL 서버는 스마트이며 존재를 위해 사용되는 알고 있으며, 시스템에 데이터를 반환합니다.
Quoth 마이크로 소프트 : http://technet.microsoft.com/en-us/library/ms189259.aspx?ppud=4
자신을 확인하려면 다음을 실행하십시오 :
SELECT whatever FROM yourtable WHERE EXISTS( SELECT 1/0 FROM someothertable WHERE a_valid_clause )
실제로 SELECT 목록에 뭔가를하고있는 경우, 그것은 제로 오류로 사업부를 던질 것입니다. 그것은하지 않습니다.
편집 : 참고는 SQL 표준이 실제로 이것에 대해 이야기합니다.
ANSI SQL 1992 표준 페이지 191 http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
-
==============================
2.이 오해하는 이유는 아마도 그것 때문에 모든 열을 읽는 끝날 것이라는 믿음이다. 그렇지 않은 것을 쉽게 알 수있다.
이 오해하는 이유는 아마도 그것 때문에 모든 열을 읽는 끝날 것이라는 믿음이다. 그렇지 않은 것을 쉽게 알 수있다.
CREATE TABLE T ( X INT PRIMARY KEY, Y INT, Z CHAR(8000) ) CREATE NONCLUSTERED INDEX NarrowIndex ON T(Y) IF EXISTS (SELECT * FROM T) PRINT 'Y'
계획을 제공합니다
SQL Server가 인덱스가 모든 열을 포함하지 않는다는 사실에도 불구하고 결과를 확인하기 위해 사용할 수있는 좁은 인덱스를 사용할 수 있었다이 보여줍니다. 인덱스 액세스 세미 조인 연산자하에있는이 즉시 첫 번째 행으로 리턴 스캔 막을 수 있다는 것을 의미한다.
그것은 분명하다 그래서 위의 믿음은 잘못된 것입니다.
그러나 쿼리 최적화 팀의 코너 커닝햄은 그가 일반적으로는 쿼리의 편집에있는 작은 성능 차이를 만들 수 있습니다이 경우에 하나를 선택 사용하는 여기에 설명합니다.
나는 컬럼의 다양한 숫자 빈 테이블이 쿼리를 표현하는 네 가지 방법을 시험했다. SELECT Other_Not_Null_Column 대 SELECT primary_key와 대 SELECT * 대 1을 선택합니다.
I는 OPTION (RECOMPILE) 초당 실행의 평균 측정을 이용하여 루프에 쿼리를 실행. 아래의 결과
+-------------+----------+---------+---------+--------------+ | Num of Cols | * | 1 | PK | Not Null col | +-------------+----------+---------+---------+--------------+ | 2 | 2043.5 | 2043.25 | 2073.5 | 2067.5 | | 4 | 2038.75 | 2041.25 | 2067.5 | 2067.5 | | 8 | 2015.75 | 2017 | 2059.75 | 2059 | | 16 | 2005.75 | 2005.25 | 2025.25 | 2035.75 | | 32 | 1963.25 | 1967.25 | 2001.25 | 1992.75 | | 64 | 1903 | 1904 | 1936.25 | 1939.75 | | 128 | 1778.75 | 1779.75 | 1799 | 1806.75 | | 256 | 1530.75 | 1526.5 | 1542.75 | 1541.25 | | 512 | 1195 | 1189.75 | 1203.75 | 1198.5 | | 1024 | 694.75 | 697 | 699 | 699.25 | +-------------+----------+---------+---------+--------------+ | Total | 17169.25 | 17171 | 17408 | 17408 | +-------------+----------+---------+---------+--------------+
알 수있는 바와 같이 SELECT 1 SELECT 사이에 일관된 우승자 *와 두 접근 (가) 무시할 수의 차이가 없다. 선택하지 널 COL 및 SELECT PK는 약간 빠른하지만 표시 않습니다.
쿼리의 네 개의 테이블 증가의 열 수와 같은 성능 저하.
테이블이 관계를 비어 같이 열 메타 데이터의 양에 의해서만 천명 보인다. COUNT (1)의 경우 아래에서 그 과정에서 어떤 시점에서 COUNT (*)에 다시됩니다 것을 쉽게 알 수있다.
SET SHOWPLAN_TEXT ON; GO SELECT COUNT(1) FROM master..spt_values
어느 다음과 같은 계획을 제공합니다
|--Compute Scalar(DEFINE:([Expr1003]=CONVERT_IMPLICIT(int,[Expr1004],0))) |--Stream Aggregate(DEFINE:([Expr1004]=Count(*))) |--Index Scan(OBJECT:([master].[dbo].[spt_values].[ix2_spt_values_nu_nc]))
SQL Server 프로세스에 디버거를 연결하고 무작위로 아래를 실행하는 동안 파괴
DECLARE @V int WHILE (1=1) SELECT @V=1 WHERE EXISTS (SELECT 1 FROM ##T) OPTION(RECOMPILE)
나는 테이블이 참 케이스를 들어 SELECT (1)가 사용되는 경우에도 시간 로딩 열 메타 데이터의 큰 비율을 (지출을 나타내는 아래 대부분의 시간의 같은과 같은 호출 스택의 모습을 1,024 열이있는 경우에 그 발견 테이블 1 열이있는 곳에 무작위로 파괴는) 10 개 시도에서 호출 스택의이 비트를 명중하지 않았다
sqlservr.exe!CMEDAccess::GetProxyBaseIntnl() - 0x1e2c79 bytes sqlservr.exe!CMEDProxyRelation::GetColumn() + 0x57 bytes sqlservr.exe!CAlgTableMetadata::LoadColumns() + 0x256 bytes sqlservr.exe!CAlgTableMetadata::Bind() + 0x15c bytes sqlservr.exe!CRelOp_Get::BindTree() + 0x98 bytes sqlservr.exe!COptExpr::BindTree() + 0x58 bytes sqlservr.exe!CRelOp_FromList::BindTree() + 0x5c bytes sqlservr.exe!COptExpr::BindTree() + 0x58 bytes sqlservr.exe!CRelOp_QuerySpec::BindTree() + 0xbe bytes sqlservr.exe!COptExpr::BindTree() + 0x58 bytes sqlservr.exe!CScaOp_Exists::BindScalarTree() + 0x72 bytes ... Lines omitted ... msvcr80.dll!_threadstartex(void * ptd=0x0031d888) Line 326 + 0x5 bytes C kernel32.dll!_BaseThreadStart@8() + 0x37 bytes
이 매뉴얼 프로파일 시도는 두 경우에 대한 컴파일 시간을 소모 기능의 매우 다른 선택을 보여줍니다 VS 2012 코드 프로파일 러 (상위 15 기능 15 가지 기능 1 열 대 1,024 열)에 의해 백업됩니다.
모두 SELECT 1 *이 버전 확인 열 권한을 바람과 사용자가 테이블의 모든 컬럼에 대한 액세스 권한이 부여되지 않은 경우 실패를 선택합니다.
예제 나는 힙에 대화에서 cribbed
CREATE USER blat WITHOUT LOGIN; GO CREATE TABLE dbo.T ( X INT PRIMARY KEY, Y INT, Z CHAR(8000) ) GO GRANT SELECT ON dbo.T TO blat; DENY SELECT ON dbo.T(Z) TO blat; GO EXECUTE AS USER = 'blat'; GO SELECT 1 WHERE EXISTS (SELECT 1 FROM T); /* ↑↑↑↑ Fails unexpectedly with The SELECT permission was denied on the column 'Z' of the object 'T', database 'tempdb', schema 'dbo'.*/ GO REVERT; DROP USER blat DROP TABLE T
하나는 작은 명백한 차이 SELECT some_not_null_col를 사용하여 단지 특정 컬럼에 대한 권한을 확인하는 바람이 있다는 것을 추측 할 수 있도록 (하지만 여전히 모든 메타 데이터를로드합니다). 아무것도 기본 테이블 증가의 열 수가 작아지는 경우 둘 사이의 비율 차이가 접근 그러나이 사실로 적합하지 않는 것 같습니다.
어쨌든 나는 밖으로 돌진되지 않고 차이가 매우 작은 쿼리 컴파일시에만 명백한 바와 같이이 양식에 내 모든 쿼리를 변경. 그 이후의 실행은 캐시 된 계획은 다음을 준 사용할 수 있도록 OPTION (RECOMPILE)을 제거.
+-------------+-----------+------------+-----------+--------------+ | Num of Cols | * | 1 | PK | Not Null col | +-------------+-----------+------------+-----------+--------------+ | 2 | 144933.25 | 145292 | 146029.25 | 143973.5 | | 4 | 146084 | 146633.5 | 146018.75 | 146581.25 | | 8 | 143145.25 | 144393.25 | 145723.5 | 144790.25 | | 16 | 145191.75 | 145174 | 144755.5 | 146666.75 | | 32 | 144624 | 145483.75 | 143531 | 145366.25 | | 64 | 145459.25 | 146175.75 | 147174.25 | 146622.5 | | 128 | 145625.75 | 143823.25 | 144132 | 144739.25 | | 256 | 145380.75 | 147224 | 146203.25 | 147078.75 | | 512 | 146045 | 145609.25 | 145149.25 | 144335.5 | | 1024 | 148280 | 148076 | 145593.25 | 146534.75 | +-------------+-----------+------------+-----------+--------------+ | Total | 1454769 | 1457884.75 | 1454310 | 1456688.75 | +-------------+-----------+------------+-----------+--------------+
사용 된 테스트 스크립트 나는 여기에서 찾을 수 있습니다
-
==============================
3.알고 가장 좋은 방법은 성능 테스트 두 버전이며, 두 버전에 대한 실행 계획을 확인하십시오. 열이 많은 테이블을 선택합니다.
알고 가장 좋은 방법은 성능 테스트 두 버전이며, 두 버전에 대한 실행 계획을 확인하십시오. 열이 많은 테이블을 선택합니다.
-
==============================
4.이 SQL Server의 차이는 없습니다 그것은 SQL Server에서 문제되지 않았어요. 최적화는이 같은 것을 알고있다. 당신이 실행 계획을 보면, 당신은 그들이 동일한 것을 볼 수 있습니다.
이 SQL Server의 차이는 없습니다 그것은 SQL Server에서 문제되지 않았어요. 최적화는이 같은 것을 알고있다. 당신이 실행 계획을 보면, 당신은 그들이 동일한 것을 볼 수 있습니다.
-
==============================
5.개인적으로 나는 그들이 동일한 쿼리 계획을 최적화하지 믿고 아주, 아주 하드를 찾을 수 있습니다. 그러나 특정 상황에서 알 수있는 유일한 방법은 그것을 테스트하는 것입니다. 당신이 할 경우 다시 신청 해주세요!
개인적으로 나는 그들이 동일한 쿼리 계획을 최적화하지 믿고 아주, 아주 하드를 찾을 수 있습니다. 그러나 특정 상황에서 알 수있는 유일한 방법은 그것을 테스트하는 것입니다. 당신이 할 경우 다시 신청 해주세요!
-
==============================
6.아니 실제 차이가 있지만 아주 작은 성능 저하가있을 수 있습니다. 당신이 필요로하는 것보다 엄지 손가락의 규칙으로 당신은 더 많은 데이터를 요구해서는 안된다.
아니 실제 차이가 있지만 아주 작은 성능 저하가있을 수 있습니다. 당신이 필요로하는 것보다 엄지 손가락의 규칙으로 당신은 더 많은 데이터를 요구해서는 안된다.
from https://stackoverflow.com/questions/1597442/subquery-using-exists-1-or-exists by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] MySQL은 시뮬레이션 지연 기능 (0) | 2020.03.16 |
---|---|
[SQL] MySQL의 문자열과 함께 작업에) (폭발의 등가 (0) | 2020.03.16 |
[SQL] WHERE 절에 알 수없는 열 (0) | 2020.03.16 |
[SQL] 같은 select 문에 의해 수와 그룹을 사용하는 방법 (0) | 2020.03.16 |
[SQL] 어떻게 java.sql.ResultSet의 크기를받을 수 있나요? (0) | 2020.03.16 |