SQL은 선언적입니까?


22

SQL에서 볼 수있는 많은 질문들이 "이것은 느리다. 어떻게 속도를 높이는가?" 또는 "이 방법을 사용하십시오. 더 빠르므로 그렇게하지 마십시오"라고 설명하는 자습서가 있습니까?

SQL의 많은 부분이 표현식이 어떻게 수행 될지, 더 잘 수행하는 지식 선택 식 스타일을 아는 것 같습니다. 이것은 선언적 프로그래밍의 한 측면으로 제곱되지 않습니다. 시스템이 계산을 생성하는 것을 지정하는 것만으로 계산을 수행하는 가장 좋은 방법을 결정하도록하는 것입니다.

SQL 엔진을 사용했는지 신경 쓰지 않아야합니까 in, exists아니면 join실제로 선언적인지 여부는 세 가지 방법 중 하나를 사용하여 합리적인 시간 내에 정확한 답변을 제공해서는 안됩니까? 이 마지막 예는 첫 번째 단락에서 언급 한 유형의 최근 게시물에 의해 프롬프트됩니다 .

인덱스

내가 사용할 수있는 가장 쉬운 예는 테이블의 인덱스를 만드는 것과 관련이 있다고 생각합니다. w3schools.com 의 괌 은 성능상의 이유로 사용자가 보이지 않는 것으로 설명하려고 시도합니다. 그들의 설명은 SQL 인덱스를 선언적이지 않은 캠프에 넣는 것으로 보이며 순수한 성능상의 이유로 일상적으로 수작업으로 추가됩니다.

그것들은 다른 모든 것보다 훨씬 더 선언적인 이상적인 SQL DB 어딘가에 관한 것이지만 좋은 사람은 그것에 대해 듣지 못하기 때문입니까?


@FrustratedWithFormsDesigner : 나는 그것이 무엇을 의미하는지 정확히 알고 있습니다. select whatever from sometable where FKValue in (select FKValue from sometable_2 where other_value = :param). exists또는로 로 다시 설명하는 방법을 이해하는 것은 쉽지 않습니다 join.
메이슨 휠러

비슷한 추론을 사용하면 정규 표현식이 "선언적인 성능을 얻기 위해이 방법으로 작성해야합니다"라는 대답을 거의 보지 못하기 때문에보다 선언적인 표현 방법이라고 생각합니다. 나는 내 두뇌를 망쳐 놓고 느린 정규 표현식에서 부정적인 표정 뒤에 또는 앞선 주장과 관련된 몇 가지 질문을 절반 만 기억할 수 있습니다.
Paddy3118 2016

성능은 구현 세부 사항입니다. 쿼리 프로세서 개발자가 우선 순위라고 생각하면 거의 모든 IN 구현의 성능이 EXISTS 및 JOIN보다 비슷하거나 더 우수 할 수 있습니다.
JustinC

1
@JustinC, 성능 지향 SQL 질문의 우세와 선언적 언어에 대한 팁을 감안할 때 세부적인 것 이상입니까?
Paddy3118 2016 년

선언적 프로그래밍 언어에 대한 명확한 정의가 없으므로 이야기 할 의미가 없습니다. 어떤 언어는 다른 언어보다 높은 수준입니다.
gardenhead

답변:


21

SQL은 이론적으로 선언적입니다. 그러나 당신은 그들이 이론과 실제의 차이점에 대해 말하는 것을 알고 있습니다 ...

핵심적으로 "선언적 프로그래밍"이라는 개념은 결코 효과적이지 않았으며, 코드를보고 "이 코드의 의도는 무엇입니까?" 그것을 쓴 사람과 같은 방식으로 지능적으로. 모든 선언적 언어의 핵심에는 AI의 도움없이 문제를 해결하기 위해 열렬히 노력하는 많은 명령 코드가 있습니다.

가장 일반적인 경우는 일반적인 경우 이므로 언어의 구현을 작성한 사람들이 알고 처리 할 수있는 좋은 방법을 찾았 기 때문에 종종 놀랍게 잘 작동합니다 . 그러나 구현자가 고려하지 않은 최첨단 사례에 대비하면 인터프리터가 코드를 훨씬 더 문자 그대로 받아 덜 효율적으로 처리해야하므로 성능이 빠르게 저하됩니다.


3
진정으로 효과가 없습니까? SQL, LINQ, Knockout.js, 프롤로그, ELM 언어 다시 확인하고 싶을 수도 있습니다. 나는 현재 대부분 선언적 기술을 사용하고 있습니다.
brian

5
@ brian : 아무도 생각하지 않은 최첨단 사건이 발생하면 모두 빨리 퇴보합니다. 나는 " 일반적인 경우에는 절대로 효과적이지 않다"고 말했을 것 입니다.
메이슨 휠러

응답이 SQL Server 데이터베이스에 저장되는 방식으로 저하되는 시점은 언제입니까? :) 프레임 워크 내에서 해결할 수없는 가장자리 케이스는 거의 없습니다. 나는 당신이 어디에서 왔는지 알지만 가장자리 케이스는 선언적 코드의 약 99 %가 얼마나 유익하고 쉽게 추론되는지에 대해 많은 고통을 유발하지 않습니다. Clojure 또는 F #이 문제를 해결하기 위해 변경 가능한 유형을 사용해야했기 때문에 나쁘다고 말하는 것과 같습니다.
brian

11
@ brian : I rarely hit an edge case in any of them that couldn't be solved within the framework.네, 요점입니다. 프레임 워크는 원래 선언 한 방식으로 해결할 수있을만큼 똑똑하지 않기 때문에 프레임 워크 내에서 해결할 수있는 방법을 찾아야 합니다.
메이슨 휠러

업데이트를 위해 select ...는 어떻습니까? 명령적인 명령 인 것 같습니다.
Jesvin Jose

6

나는 며칠 전에 SQL 최적화 후에 이것을 생각하고있었습니다. 우리는 SQL이 위키 백과의 정의에서 "선언적 언어"라는 것에 동의 할 수 있다고 생각합니다.

제어 흐름을 설명하지 않고 계산 논리를 표현하는 프로그래밍 패러다임

커튼 뒤에서 얼마나 많은 일들이 (통계를 보거나, 인덱스가 유용한 지 결정하고, 중첩, 병합 또는 해시 조인 등을 결정하는 등) 생각하는 경우, 우리는 단지 높은 수준을 제공한다는 것을 인정해야합니다 데이터베이스는 모든 하위 수준 제어 흐름 논리를 처리했습니다.

또한이 시나리오에서 때때로 데이터베이스 최적화 프로그램은 최상의 결과를 제공하기 위해 사용자의 "힌트"가 필요합니다.

"선언적"언어에 대한 또 다른 일반적인 정의는 다음과 같습니다.

원하는 계산 결과를 표현하는 단계를 설명하지 않고 원하는 계산 결과를 표현하는 프로그래밍 패러다임 ( "방법 설명, 방법 설명"으로 축약 됨)

이 정의를 수락하면 OP에 설명 된 문제가 발생합니다.

첫 번째 문제는 SQL이 "동일한 결과"를 정의하는 여러 가지 동등한 방법을 제공한다는 것입니다. 아마도 그것은 악한 것입니다. 언어에 표현력이 강할수록 같은 표현을 할 수있는 다른 방법이 더 많이있을 것입니다.

예를 들어,이 쿼리를 최적화하라는 요청을 한 번 받았습니다.

 SELECT Distinct CT.cust_type,  ct.cust_type_description 
   from customer c 
              INNER JOIN 
              Customer_type CT on c.cust_type=ct.cust_type;

유형이 고객보다 훨씬 적고 cust_type고객 테이블에 색인 이 있었으므로 다음과 같이 다시 작성하여 크게 개선했습니다.

 SELECT CT.cust_type,  ct.cust_type_description 
   from Customer_type CT
  Where exists ( select 1 from customer c 
                  Where c.cust_type=ct.cust_type);

이 특정 사례에서 개발자에게 달성하고자하는 것을 물었을 때 "최소한 한 명의 고객을 보유한 모든 고객 유형을 원했습니다"라고 말하면서 우연히 옵티 마이저 쿼리를 설명 할 수있는 방법입니다.

따라서 동등하고 더 효율적인 쿼리를 찾을 수 있다면 옵티마이 저가 왜 그렇게 할 수 없습니까?

가장 좋은 추측은 두 가지 주요 이유 때문입니다.

SQL은 논리를 표현합니다 :

SQL이 높은 수준의 논리를 표현하기 때문에 옵티마이 저가 우리와 우리의 논리를 "우수하게"원할까요? 나는 항상 최적화 프로그램이 가장 효율적인 실행 경로를 선택하도록 강요하지 않았다면 열정적으로 "예"를 외칠 것이다. 나는 그 아이디어가 옵티마이 저가 최선을 다할 수 있도록하는 것이지만 (논리를 수정하는 것) 무언가가 미쳤을 때 구조에 올 수있는 "힌트 메커니즘"을 제공 할 수 있다고 생각한다 (바퀴와 브레이크가 자율 주행 차).

더 많은 선택 = 더 많은 시간

최고의 RDBMS 옵티 마이저조차도 가능한 모든 실행 경로를 테스트하지는 않습니다. 실제로 빠르지 않아야합니다. 100ms마다 최고의 경로를 선택해야 할 때마다 100ms에서 10ms까지 쿼리를 최적화하는 것이 얼마나 좋을까요? 그리고 그것은 "고수준 논리"를 존중하는 옵티 마이저와 함께합니다. 동등한 SQL 조회도 모두 테스트해야하는 경우 최적화 시간이 여러 번 증가 할 수 있습니다.

RDBMS가 실제로 할 수없는 쿼리 재 작성의 또 다른 좋은 예는 ( 이 흥미로운 블로그 게시물에서 )

SELECT t1.id, t1.value, SUM(t2.value)
  FROM mytable t1
       JOIN mytable t2
         ON t2.id <= t1.id
 GROUP BY t1.id, t1.value;

이처럼 쓸 수있는 것 (분석 기능 필요)

 SELECT id, value, SUM(t1.value) OVER (ORDER BY id)
   FROM mytable

1
조인을에 다시 쓰는 예가 흥미 롭습니다. SQL 개발자에게 감동을주는 한 가지 규칙은 DISTINCT를 사용하는 것이 코드 냄새입니다. 쿼리 나 데이터 모델이 잘못되었을 가능성이 있으며 다른 접근 방식을 찾아야합니다.
David Aldridge
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.