문제

정규화된 주문 데이터로 구성된 대규모 데이터베이스가 있는데 보고를 위한 쿼리 속도가 매우 느려지고 있습니다.내가 보고서에 사용하는 쿼리 중 상당수는 5~6개의 테이블을 조인하고 수만 또는 수십만 줄을 검사해야 합니다.

쿼리가 많고 대부분 서버 부하를 줄이고 속도를 높이기 위해 최대한 최적화되었습니다.이제는 비정규화된 형식으로 데이터 복사본을 보관해야 할 때라고 생각합니다.

접근 방식에 대한 아이디어가 있나요?몇 가지 최악의 쿼리부터 시작해서 거기서부터 시작해야 합니까?

도움이 되었습니까?

해결책

나는 mysql보다 mssql에 대해 더 많이 알고 있지만, 당신이 말하는 조인 수나 행 수가 올바른 인덱스에 너무 많은 문제를 일으킬 것이라고 생각하지 않습니다.누락된 항목이 있는지 확인하기 위해 쿼리 계획을 분석했습니까?

http://dev.mysql.com/doc/refman/5.0/en/explain.html

즉, 인덱스에 만족하고 다른 모든 방법을 모두 사용했다면 비정규화가 정답일 수 있습니다.문제가 되는 쿼리가 한두 개만 있는 경우 수동 접근 방식이 적절할 수 있지만, 데이터 큐브를 개발하기 위한 플랫폼을 만드는 데는 일종의 데이터 웨어하우징 도구가 더 나을 수 있습니다.

이 주제를 다루는 사이트는 다음과 같습니다.

http://www.meansandends.com/mysql-data-warehouse/?link_body%2Fbody=%7Bincl%3AAggregation%7D

다음은 한 번에 몇 가지만 수행하는 경우(OLTP 테이블을 교체하지 않고 보고 목적으로 새 테이블을 만드는 경우) 비정규 쿼리를 간단하게 유지하는 데 사용할 수 있는 간단한 기술입니다.애플리케이션에 다음 쿼리가 있다고 가정해 보겠습니다.

select a.name, b.address from tbla a 
join tblb b on b.fk_a_id = a.id where a.id=1

비정규화된 테이블을 생성하고 거의 동일한 쿼리로 채울 수 있습니다.

create table tbl_ab (a_id, a_name, b_address); 
-- (types elided)

밑줄이 사용하는 테이블 별칭과 일치하는지 확인하세요.

insert tbl_ab select a.id, a.name, b.address from tbla a
join tblb b on b.fk_a_id = a.id 
-- no where clause because you want everything

그런 다음 새로운 비정규화된 테이블을 사용하도록 앱을 수정하려면 밑줄 점을 전환하세요.

select a_name as name, b_address as address 
from tbl_ab where a_id = 1;

대규모 쿼리의 경우 이는 많은 시간을 절약할 수 있고 데이터의 출처를 명확하게 하며 이미 가지고 있는 쿼리를 재사용할 수 있습니다.

기억하세요. 저는 이것을 최후의 수단으로만 옹호할 뿐입니다.나는 당신에게 도움이 될 몇 가지 색인이 있다고 확신합니다.그리고 비정규화할 때 디스크의 추가 공간을 고려하고 쿼리를 실행하여 새 테이블을 채울 시기를 파악하는 것을 잊지 마십시오.이는 아마도 밤이나 활동이 적을 때 이루어져야 합니다.물론 해당 테이블의 데이터는 정확히 최신 상태가 될 수 없습니다.

[또 다른 편집] 생성한 새 테이블도 인덱싱되어야 한다는 점을 잊지 마세요!좋은 점은 대량 삽입을 제외하면 테이블에 선택 항목만 표시되므로 업데이트 잠금 경합에 대해 걱정하지 않고 마음껏 색인할 수 있다는 것입니다.

다른 팁

MySQL 5는 지원합니다 견해, 이 시나리오에서는 도움이 될 수 있습니다.이미 많은 최적화를 수행한 것처럼 들리지만, 그렇지 않은 경우 MySQL의 설명하다 실제로 사용되는 인덱스와 쿼리 속도를 저하시키는 요소를 확인하는 구문입니다.

데이터 정규화에 관한 한(뷰를 사용하든지 더 효율적인 방식으로 데이터를 복제하든 관계없이) 가장 느린 쿼리부터 시작하여 작업을 진행하는 것이 좋은 접근 방식이라고 생각합니다.

이것이 약간 접선적이라는 것을 알고 있지만 추가할 수 있는 인덱스가 더 있는지 확인해 보셨나요?

저는 DB에 대한 지식이 많지는 않지만 최근에 데이터베이스 관련 작업을 많이 하고 있는데, 인덱스를 추가하는 것만으로도 쿼리가 많이 향상될 수 있다는 것을 알게 되었습니다.

우리는 DB2를 사용하고 있으며 db2expln 및 db2advis라는 명령이 있는데, 첫 번째는 테이블 스캔과 인덱스 스캔이 사용되는지 여부를 나타내고 두 번째는 성능 향상을 위해 추가할 수 있는 인덱스를 추천합니다.MySQL에도 비슷한 도구가 있다고 확신합니다 ...

어쨌든, 아직 고려하지 않은 부분이라면 제게 많은 도움이 되었어요...하지만 이미 이 길을 택했다면, 그것은 당신이 찾고 있는 것이 아닐 것 같습니다.

또 다른 가능성은 "구체화된 뷰"(또는 DB2에서 호출하는 방식)로, 기본적으로 여러 테이블의 일부로 구성된 테이블을 지정할 수 있습니다.따라서 실제 열을 정규화하는 대신 이 뷰를 제공하여 데이터에 액세스할 수 있습니다.그러나 이것이 삽입/업데이트/삭제에 심각한 성능 영향을 미치는지 여부는 알 수 없습니다(그러나 "구체화"된 경우 값이 물리적으로 별도로 저장되므로 선택에 도움이 됩니다).

다른 의견 중 일부와 일치하여 귀하의 색인 생성을 확실히 살펴볼 것입니다.

제가 올해 초 MySQL 데이터베이스에서 발견한 것 중 하나는 복합 인덱스의 힘이었습니다.예를 들어, 날짜 범위에 대한 주문 번호를 보고하는 경우 주문 번호 및 주문 날짜 열에 대한 복합 색인이 도움이 될 수 있습니다.나는 MySQL이 쿼리에 하나의 인덱스만 사용할 수 있다고 생각합니다. 따라서 주문 번호와 주문 날짜에 대해 별도의 인덱스가 있는 경우 그 중 하나만 사용하도록 결정해야 합니다.EXPLAIN 명령을 사용하면 이를 확인하는 데 도움이 될 수 있습니다.

좋은 인덱스(수많은 복합 인덱스 포함)의 성능을 표시하기 위해 데이터베이스의 3개 테이블을 조인하는 쿼리를 실행하고 대부분의 경우 거의 즉각적인 결과를 얻을 수 있습니다.더 복잡한 보고의 경우 대부분의 쿼리가 10초 이내에 실행됩니다.이 3개의 테이블에는 각각 3,300만 개, 1억 1,000만 개, 1억 4천만 개의 행이 있습니다.또한 데이터베이스에서 가장 일반적인 쿼리 속도를 높이기 위해 이미 이를 약간 정규화했습니다.

테이블 및 보고 쿼리 유형에 대한 추가 정보를 통해 추가 제안이 가능할 수 있습니다.

MySQL의 경우 나는 이 강연을 좋아합니다: 실제 웹:성능 및 확장성, MySQL 에디션.여기에는 MySQL의 속도를 높이기 위한 다양한 조언이 포함되어 있습니다.

임시 테이블을 선택한 다음 해당 임시 테이블에서 쿼리를 수행하는 것을 고려할 수도 있습니다.이렇게 하면 실행하는 모든 단일 쿼리에 대해 테이블을 다시 조인할 필요가 없습니다(물론 수많은 쿼리에 임시 테이블을 사용할 수 있다고 가정).이는 기본적으로 비정규화된 데이터를 제공하지만 선택 호출만 수행하는 경우 데이터 일관성에 대한 걱정은 없습니다.

이전 답변에 더해, 일부 상황에서 우리가 취한 또 다른 접근 방식은 주요 보고 데이터를 별도의 요약 테이블에 저장하는 것입니다.비정규화 및 최적화 후에도 속도가 느려지는 특정 보고 쿼리가 있으며, 테이블을 만들고 한 달 내내 누적 합계 또는 요약 정보를 저장하면 월말 보고도 훨씬 빨라진다는 사실을 발견했습니다.

우리는 이 접근 방식이 이미 작동 중인 것을 손상시키지 않았기 때문에 구현하기 쉽다는 것을 알았습니다. 이는 단지 특정 지점에 추가 데이터베이스 삽입일 뿐입니다.

나는 복합 인덱스를 가지고 놀았고 몇 가지 실질적인 이점을 보았습니다. 아마도 이것이 나를 절약할 수 있는지 알아보기 위해 몇 가지 테스트를 설정할 것입니다. 적어도 조금 더 오랫동안.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top