2010-11-26 4 views
11

나는 하둡을 읽고있다 : 톰 화이트의 결정적인 가이드. 챕터 13.6 "HBase와 RDMS"에서 그는 많은 데이터가있는 경우 최근 항목 10 개를 얻는 것과 같은 간단한 쿼리조차도 매우 비싸고 Python과 PL/SQL을 사용하여 다시 작성해야한다고했습니다.Hadoop에 설명 된대로 RDBMS가 좋지 않습니까?

그는 예를 들어 다음 쿼리 제공 :

SELECT id, stamp, type FROM streams 
WHERE type IN ('type1','type2','type3','type4',...,'typeN') 
ORDER BY stamp DESC LIMIT 10 OFFSET 0; 

을 다음과 같이 말한다 : "는 RDBMS 쿼리 플래너 취급이 쿼리를 다음과 같이

MERGE (
    SELECT id, stamp, type FROM streams 
    WHERE type = 'type1' ORDER BY stamp DESC, 
    ..., 
    SELECT id, stamp, type FROM streams 
    WHERE type = 'typeK' ORDER BY stamp DESC 
) ORDER BY stamp DESC LIMIT 10 OFFSET 0; 

여기서 문제는 우리가 있다는 것입니다 이후에는 상위 10 개의 ID 만 표시되지만 플래너의 쿼리는 실제로 전체 병합을 구체화 한 다음 끝 부분을 제한합니다. 까지 힙을 수행 한 사용자 정의 PL/Python 스크립트 을 작성했습니다. ... 거의 모든 경우에,이

예상 perforamnce 및 expermiental 결과

나는 데이터 세트를 상상할 수 없었다 ... 네이티브 SQL 구현과 쿼리 계획의 전략 상회 그 같은 간단한 질의 권리를 수행하기 위해 pl/python을 작성해야하는 문제가 발생합니다. 그래서 나는이 문제에 대해 잠시 동안 놀았으며 다음 관측을 제안했습니다.

이러한 쿼리의 성능은 O (KlogN)로 제한됩니다. 이 번역 될 수 있기 때문에 그렇게 뭔가를 다음과 같이

SELECT * FROM (
    SELECT id, stamp, type FROM streams 
    WHERE type = 'type1' ORDER BY stamp DESC LIMIT 10, 
    UNION 
    ..., 
    SELECT id, stamp, type FROM streams 
    WHERE type = 'typeK' ORDER BY stamp DESC LIMIT 10 
) t ORDER BY stamp DESC LIMIT 10; 

(각 쿼리의 'LIMIT (10)를'주의 BTW 내가 주문 노동 조합을 제한 할 수 없다는 것을 알고하지만 난 선택을 포장 밖으로 제거했습니다. 가독성을 위해)

각 하위 쿼리는 색인 O (logN)에서 올바른 위치를 찾고 10 개의 항목을 반환하는만큼 빠르게 실행되어야합니다. 우리가 K 회 반복한다면 우리는 O (KlogN)를 얻는다.

쿼리 플래너가 너무 나빠서 첫 번째 쿼리를 최적화 할 수 없더라도 pl/python에 아무 것도 쓰지 않고 원하는 성능을 얻을 수 있습니다.

내 계산을 다시 확인하기 위해 9,000,000 개의 테스트 레코드로 채워진 하나의 postgresql보다 위에있는 쿼리를 실행했습니다. 결과는 두 쿼리가 모두 첫 쿼리의 경우 매우 빨랐으며 두 번째 쿼리의 경우 300ms였습니다 (유니온이있는 쿼리).

따라서 쿼리가 9,000,000 (logn = 23) 개의 레코드로 100ms 실행되고 9,000,000,000 (logn = 33) 개의 레코드로 실행되는 경우 140ms로 실행되어야합니다.

질문

  • 당신은 위의 추론에 어떤 결함을 볼 수 있습니까?
  • 위와 같은 쿼리를 pl/python으로 다시 작성해야하는 데이터 세트를 상상할 수 있습니까?
  • O (K log n)에서 이러한 쿼리가 작동하지 않는 상황이 있습니까?
+0

아니요, 그렇지 않습니다. 어떤 데이터베이스는 필드의 필터에있는 각 항목에 대해 전체 테이블을 한 번 쿼리하고 모든 레코드를 병합 한 다음 주문한 다음 끝에 제한을 수행합니까? – MkV

답변

6

적어도 RDMBS 쿼리 계획자가 해당 솔루션을 쿼리에 사용한다는 주장은 PostgreSQL 9.0에서 올바르지 않습니다. 다른 플랫폼에서도 마찬가지입니다. 나는 유사한 쿼리 빠른 테스트를했다 :

여기
explain select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by client_attribute_id desc limit 10; 

                 QUERY PLAN 
----------------------------------------------------------------------------------------------------------------------- 
Limit (cost=0.00..0.93 rows=10 width=85) 
    -> Index Scan Backward using client_attribute_pkey on client_attribute (cost=0.00..15516.47 rows=167234 width=85) 
     Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[])) 
(3 rows) 

client_attribute_id 색인, 그래서 desired-가 다시 인덱스를 통해 산책 필터를 적용하고 출력이 한계에 도달 할 때 중지로 정확하게 수행한다. 순서 열이 인덱싱되지 않은 경우

는 일종의 테이블 스캔 및 requierd이지만, 하나의 테이블 스캔 :

explain analyze select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by updated desc limit 10; 

                   QUERY PLAN 
--------------------------------------------------------------------------------------------------------------------------------------- 
Limit (cost=13647.00..13647.03 rows=10 width=85) (actual time=180.961..180.964 rows=10 loops=1) 
    -> Sort (cost=13647.00..14065.09 rows=167234 width=85) (actual time=180.960..180.961 rows=10 loops=1) 
     Sort Key: updated 
     Sort Method: top-N heapsort Memory: 26kB 
     -> Seq Scan on client_attribute (cost=0.00..10033.14 rows=167234 width=85) (actual time=0.010..106.791 rows=208325 loops=1) 
       Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[])) 

이것은 순차 검색의 과정을 통해 상위 10 개 결과를 유지하기 위해 힙 정렬을 사용하여 이는 자신이 쓴 해결책과 정확히 일치합니다.

4

나는 Tom White가 관계형 데이터베이스가 "나쁜"것이라고 말하지 않는다고 생각합니다. 비 관계형, 비 집합 기반 데이터에는 최적이 아닙니다.

깊은 개체 그래프는 관계형 데이터베이스에 적합하지 않은 것으로 잘 알려져 있습니다. 일반적으로 어셈블리는 기하학적 데이터의 CAD 표현과 같은 문제에서 발견됩니다. 여기에서 어셈블리는 파트 어셈블리 어셈블리로 구성됩니다. 기준 사슬은 참으로 길다.

개체 및 그래프 데이터베이스는 90 년대 초에 알고 있었기 때문에 이러한 종류의 문제에 대한 솔루션이었습니다.

관계형 데이터베이스는 관계형 세트 기반 데이터에 적합합니다. 그러나 모든 데이터는 해당 범주에 속하지 않습니다. 이것이 바로 NoSQL이 마인드 쉐어를 얻는 이유입니다.

나는 그것이 당신이 인용 한 예가 무엇이라고 생각합니다.

+3

그가 말한 것처럼 보이는 것은 RDBMS의 쿼리 계획자가 나쁘다는 것입니다. 파이썬으로 작성하는 것이 더 낫지 만 실제 RDBMS에서 사용되는 실제 쿼리 계획을 대표하지 않는 작성된 예제를 사용하는 것입니다. – MkV

1

RDBMS는 사용자가 생각하지 못한 쿼리를위한 것입니다. 원하는 내용이 정확하면 가장 최적의 솔루션을 적용 할 수 있습니다.

1

SQL 또는 NoSQL을 사용하면 잘못된 방식으로 쿼리를 설계하면 성능이 심각해질 수 있습니다.

where 절에 timestamp에 대한 점검을 추가하여이 예제를 수정합니다. 많은 양의 데이터가있는 경우 가장 최근의 10 개 항목이 마지막 순간에 있다고 가정 할 수 있습니다. 그렇다면 지난 달의 모든 항목을 읽고 정렬 해보십시오.

기본적으로 ID로 레코드를 찾을 수 있기 때문에 필요한 레코드를 찾기 위해 전체 데이터 세트를로드해야하기 때문에 동일한 예제를 사용하여 NoSQL을보기 좋게 만들 수 있습니다. 중요한 쿼리에 대한 SQL 성능보다 나은 여러 보조/사용자 지정 인덱스를 설정하십시오.

관련 문제