데이터베이스 재 설계 기회 :이 센서 데이터 수집에 사용할 테이블 설계는 무엇입니까?


13

배경

약 2000 개의 센서 네트워크가 있으며 각 센서에는 약 100 개의 데이터 포인트가 있으며 10 분 간격으로 수집합니다. 이 데이터 포인트는 일반적으로 int 값이지만 일부는 문자열과 부동 소수점입니다. 이 데이터는 가능하면 더 효율적으로 90 일 동안 저장해야합니다.

데이터베이스 디자인

이 프로젝트를 처음 수행했을 때 각 센서마다 쉼표로 구분 된 파일을 작성하는 C # 앱을 작성했습니다. 당시에는 트렌드를보고 싶을 때 Excel에서 csv를 열고 필요에 따라 그래프를 만들었습니다.

상황이 커지고 MySQL 데이터베이스로 전환했습니다. 각 센서마다 테이블을 만들었습니다 (예, 테이블이 많이 있습니다). 잘 작동했지만 몇 가지 제한 사항이 있습니다. 테이블이 너무 많으면 특정 값을 찾을 때 모든 센서에서 데이터를 찾는 쿼리를 작성하는 것이 불가능합니다.

다음 버전에서는 Microsoft SQL Server Express로 전환하여 모든 센서 데이터를 하나의 큰 테이블에 넣었습니다. 이것은 또한 작동하며, 관심있는 모든 센서 중에서 값을 찾기 위해 쿼리를 수행 할 수 있습니다. 그러나 Express 버전의 10GB 제한에 도달했으며 SQL Server Standard에 투자하기보다는 MySQL로 다시 전환하기로 결정했습니다.

질문

MySQL의 성능과 확장성에 만족하지만 모든 데이터를 한 테이블에 넣는 방법이 최선인지 확실하지 않습니다. 단일 테이블의 10GB는 다른 디자인을 요구하는 것 같습니다. 그래프를 작성하기 위해 데이터를 쿼리해야 할 필요성은 여전히 ​​남아 있으며 90 일 동안 한 센서의 온도 데이터를 그래프로 표시하는 쿼리의 성능 문제가 있을지 걱정됩니다. 즉, 그래프는 관심있는 센서를 분리하기 위해 SQL이 데이터 더미를 정렬 할 때까지 기다리지 않고 빠르게 생성 할 수있는 것이어야합니다.

성능을 향상시키기 위해이 테이블을 분할해야합니까? 아니면 그러한 큰 테이블을 갖는 것이 드문 일이 아닌가?

센서 ID 및 타임 스탬프 열에 대한 인덱스가 있는데 이는 쿼리의 경계를 정의하는 것과 거의 같습니다. (즉, 시간 A에서 시간 B까지 센서 X에 대한 데이터를 얻습니다).

샤딩 및 파티셔닝에 대해 조금 읽었지만이 경우에는 적절하다고 생각하지 않습니다.


편집하다:

지금까지 의견과 답변을 바탕으로 추가 정보가 도움이 될 수 있습니다.

무기한 저장 공간 : 현재 90 일이 지난 데이터를 저장하지 않습니다. 매일 90 일보다 오래된 데이터를 제거하는 쿼리를 실행합니다. 앞으로 중요 해지면 더 많이 저장하지만 지금은 충분합니다. 이는 크기를 확인하고 성능을 높게 유지하는 데 도움이됩니다.

엔진 유형 : 원래 MySQL 구현은 MyISAM을 사용했습니다. 이번에는 새로운 구현 (다수 대신 하나의 데이터 테이블)을 위해 테이블을 생성 할 때 기본적으로 InnoDB로 설정되었습니다. 나는 하나 또는 다른 것에 대한 요구 사항이 있다고 생각하지 않습니다.

정규화 : 데이터 수집 테이블 외에 다른 테이블도 있습니다. 이 지원 테이블에는 센서의 네트워크 정보, 사용자의 로그인 정보 등과 같은 항목이 저장됩니다. 정규화 할 것이 많지 않습니다 (내가 아는 한). 데이터 테이블에 열이 많은 이유는 각 센서에 많은 변수가 있기 때문입니다. (여러 온도, 조명 수준, 기압 등) 나에게 정규화는 중복 데이터 또는 반복 그룹이 없음을 의미합니다. (적어도 1NF의 경우) 주어진 센서에 대해 특정 시간에 모든 값을 저장하려면 하나의 데이터 행이 필요하며 여기에 관련된 1 : N 관계는 없습니다.

테이블을 기능적으로 분리하여 한 테이블의 모든 온도 관련 값과 다른 공기 압력 관련 값을 만들 수 있습니다. 이렇게하면 온도 전용 쿼리를 만드는 사람의 효율성이 향상 될 수 있지만 모든 데이터를 한 번에 삽입해야합니다. 그럼에도 불구하고 효율성 향상은 SELECT 작업에 유용 할 수 있습니다. 분명히 사용자가 데이터를 요청하는 빈도에 따라 테이블을 세로로 분리하는 것이 좋습니다. 아마도 이것이 내가해야 할 전부입니다. 내 질문을 할 때 이것이 가치가 있다는 확인을 찾고 있다고 가정합니다.


편집 2 :

데이터 사용 : 일반적으로 문제가있는 항목에만 초점을 맞추기 때문에 궁극적으로 많은 데이터를 보거나 필요로하지 않습니다. 그러나 문제 를 찾기 위해 다양한 도구를 사용하여 데이터를 검색하고 확대 할 항목을 결정합니다.

예를 들어, 메모리 사용 값 (고객 별 독점 소프트웨어 프로그램)과 재부팅 / 크래시 사이의 상관 관계를 발견했습니다. 내가 수집하는 데이터 포인트 중 하나는이 메모리 사용량과 관련이 있으며 특정 메모리 사용량을 초과 한 후 장치가 불안정 해지는 것을 보여주기 위해 기록 데이터를 볼 수있었습니다. 현재이 소프트웨어를 실행하는 장치의 하위 집합에 대해이 값을 확인하고 너무 높은 경우 재부팅 명령을 실행합니다. 이것이 발견 될 때까지, 나는이 데이터를 수집하는 것이 가치 있다고 생각하지 않았습니다.

이러한 이유로, 나는 가치가 의심스러운 경우에도 약 100 개의 데이터 포인트가 수집되고 저장되도록 유지했습니다. 그러나 일상적인 일상적인 사용에서 사용자는 일반적으로 이러한 매개 변수 수십 개를 검사합니다. 사용자가 특정 지역에 관심을 가지면 소프트웨어를 사용하여 수십 개의 센서에 대한 데이터의 그래프 또는 스프레드 시트를 생성 할 수 있습니다. 온도, 기압 및 조도 등을 나타내는 2 ~ 3 개의 플롯 선이있는 30 일 그래프를 보는 것은 드문 일이 아닙니다. 이렇게하면 다음과 비슷한 쿼리가 실행됩니다.

SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);

(각 센서마다 자체 테이블이있는 원래 MySQL 버전에서는 세 개의 개별 쿼리가 발행되지만 결과는 소프트웨어로 결합되어 그래프를 작성합니다.)

data테이블에 너무 많은 행 (~ 1 천만)이 포함되어 있기 때문에 idand에 인덱스가 있음에도 불구하고 data_timestamp성능은 다중 테이블 시나리오보다 훨씬 나쁩니다 (이 예제에서는 1 초 미만이 아닌 9 초 내에 4500 개의 행이 반환 됨). 다중 테이블 스키마에서 특정 기준에 맞는 센서를 찾는 기능은 실제로 제로이므로 단일 테이블로 이동하는 이유가 있습니다.

이 유형의 쿼리는 여러 사용자가 서로 다른 데이터 그룹을 선택하고 각 결과에서 그래프를 비교할 때 빠르게 연속해서 수행 할 수 있습니다. 그래프 또는 스프레드 시트 당 거의 10 초 정도 기다리는 것이 상당히 실망 스러울 수 있습니다.

90 일 후에 데이터가 삭제됩니다. 아카이브 될 수 있지만 현재 요구 사항은 아닙니다.

이 정보가 수집 및 저장 후 데이터가 사용되는 방식을보다 적절하게 보여줄 수 있기를 바랍니다.


이 질문은 얻을 들어 바로 답을 데이터가 실제로 사용하는 방법, 당신은 아마에 확장한다. 지금까지 제공 한 정보의 깊이에 대한 곡선보다 앞서 있지만 잘못된 각도에서 질문을 할 수 있습니다.
Mark Storey-Smith

좋은 지적, @Mark, 나는 그것에 대해서도 자세히 설명 할 것이다. 나는 그것이 압도 될 것이라는 두려움에 대해 너무 오랫동안 질문하지 않으려 고 노력했다.
JYelton

답변:


5

큰 이유로 테이블을 분할하는 것에 대해 생각해야합니다.

거대한 테이블에있는 모든 인덱스, 심지어 하나의 인덱스 만 있으면 INSERT, UPDATE 및 DELETE를 실행할 때 인덱스 유지 관리를 수행하기 위해 많은 CPU로드 및 디스크 I / O를 생성 할 수 있습니다.

2011 년 10 월 7 일 에 테이블 분할이 큰 도움이되는 이유 대한 이전 게시물을 썼습니다 . 다음은 지난 게시물에서 발췌 한 것입니다.

데이터 분할은 동일한 클래스에 논리적이고 응집력있는 데이터를 그룹화하는 역할을합니다. 데이터가 올바르게 그룹화되어 있으면 각 파티션 검색 성능을 고려해야합니다. 논리 파티셔닝을 달성하면 검색 시간에 집중하십시오. ID로만 데이터를 분리하는 경우 읽기 또는 쓰기를 위해 많은 데이터 행에 액세스하지 못할 수 있습니다. 가장 중요한 고려 사항은 다음과 같습니다. 가장 자주 액세스하는 모든 ID를 찾아서 파티션합니다. 자주 액세스하지 않는 모든 ID는 하나의 큰 아카이브 테이블에 있어야하며,이 인덱스는 '블루 문에서 한 번'쿼리에 대한 인덱스 조회로 여전히 액세스 할 수 있습니다.

나중에 내 게시물 전체 를 읽을 수 있습니다 .

추격을 바로 잡으려면 10GB 테이블에서 거의 사용되지 않는 데이터를 조사하고 찾아야합니다. 이 데이터는 기록 특성에 대한 임시 쿼리가 필요한 경우 쉽게 액세스 할 수있는 아카이브 테이블에 배치해야합니다. 10GB에서 그 뒤에 OPTIMIZE TABLE10GB 테이블 에서 해당 아카이브를 마이그레이션 하면 작업 세트가 더 빨리 SELECT, INSERT, UPDATE 및 DELETE를 실행할 수 있습니다. DDL조차도 10GB 테이블보다 2GB 작업 세트에서 더 빠릅니다.

업데이트 2012-02-24 16:19 EDT

고려해야 할 두 가지 사항

  1. 귀하의 의견으로는 정규화가 필요한 것 같습니다.
  2. 90 일이 지난 모든 것을 아카이브 테이블로 마이그레이션해야하지만 여전히 아카이브와 작업 세트에 동시에 액세스해야합니다. 데이터가 모두 MyISAM이면 MERGE 스토리지 엔진을 사용하는 것이 좋습니다. 먼저 작업 세트 MyISAM 테이블과 아카이브 MyISAM 테이블을 통합하는 MERGE 테이블 맵을 작성하십시오. 하나의 MyISAM 테이블에 91 일 미만의 데이터를 보관하고 90 일이 지난 데이터를 아카이브로 롤오버합니다. MERGE 테이블 맵만 쿼리합니다.

사용 방법에 대한 두 가지 게시물이 있습니다.

여기에 많은 열이있는 테이블에 추가 게시물이 있습니다.

MySQL에 열이 너무 많습니다


덜 빈번한 컬럼이 있지만 모든 센서는 거의 같은 비율의주의를받습니다. 따라서 테이블을 세로로 나누는 것이 유리할 것이라고 상상할 수 있습니다. 예를 들어, 20 열 테이블 (자주 액세스) 및 80 열 테이블 (자주 액세스) 이것이 분할과 같은 것인지 확실하지 않습니다.
JYelton

편집 해 주셔서 감사합니다. "MySQL에 너무 많은 열"에 대한 귀하의 게시물을 읽었습니다. 유용한 추가 요점으로 내 질문을 편집하겠습니다.
JYelton

5

흥미 롭다 ... 모든 센서가 같은 종류의 데이터를 생산한다면 모두 같은 테이블에 두는 것이 합리적이지만, 그 정도의 데이터로 성능에 대해 걱정하는 이유를 알 수 있습니다.

그래프를 생성하는 데 보통 90 일이 있습니까? 그렇다면 90 일 전부터 오늘까지 데이터를 저장하는 기본 센서 데이터 테이블과 그보다 오래된 모든 데이터는 보관 테이블에 저장됩니다. 이는 보고서가 생성되는 테이블의 크기를 줄이는 데 도움이 될 수 있으며 10GB의 대부분의 데이터는 기본 테이블이 아닌 아카이브 테이블에있을 것입니다. 보관 작업은 매일 밤 실행되도록 예약 할 수 있습니다.

또한 보고서를 생성하기에 더 적합한 구조로 데이터를 저장하는 별도의보고 데이터베이스를 구축하는 것도 고려해 볼 수 있습니다. 가능한 경우) 생성하고 정기적으로 (예 : 야간) 기본 데이터베이스에서 다시 채 웁니다. 물론 최신 데이터로 생성 된 보고서가 필요한 경우에는 제대로 작동하지 않을 수 있습니다.


이 시점에서 90 일이 지난 것을 저장하는 것은 필요하지 않지만 좋을 것입니다. "보관"테이블에 저장하는 것이 가장 좋습니다. 그래프와 데이터 분석은 단 몇 시간에서 90 일까지입니다. 대부분의 그래프 요청은 지난 주 정도의 데이터 만 사용하지만 90 일 그래프가 일반적입니다. 우리 회사는 아직 더 긴 보고서를 요청하지 않았습니다.
JYelton

@JYelton :이 방법에는 원하는만큼 많은 계층이있을 수 있습니다. 최신 테이블은 오늘에서만 가능합니다. 다음 테이블은 오늘부터 2 주 전에있을 수 있습니다. 다음 표는 오늘에서 90 일 전에있을 수 있습니다. 마지막 테이블은 모든 것이 가능합니다.
FrustratedWithFormsDesigner

내가 당신을 올바르게 이해한다면, 당신은 테이블을 복제하려고하지만 다른 기간 적용 범위를 갖습니다. 따라서 누군가가 7 일 보고서를 요청하면 일주일 만 돌아가는 테이블이 활용됩니다. 그런 다음 8 일로 확장되면 다음으로 큰 테이블 (예 : 30 일)이 활용됩니까? 이것은 단기간 쿼리의 속도를 확실히 향상시킬 수 있지만, 계층화 된 테이블을 처리하기위한 저렴한 스토리지 비용 (저렴한 비용)과 프로그래밍 로직을 제공합니다.
JYelton

@JYelton : 예, 당신이 올바르게 이해한다고 생각합니다. 쿼리 시간 범위가 표준 (오늘-1 일, 오늘-7 일, 오늘-30 일, 오늘-90 일) 인 경우 항상 어떤 테이블을 알 수 있는지 너무 어려울 것이라고 생각하지 않습니다. 히트. 범위의 시작이 현재 날짜가 아닌 시간 범위의 길이가 다양 할 수 있다면, 구현할 논리가 까다로워지고 여러 테이블에 대한 UNION 연산으로 크로스 테이블에 대한 쿼리가 비싸 질 수 있습니다.
FrustratedWithFormsDesigner
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.