데이터베이스에서 쓸모없는 외래 키를 찾는 방법

9805 단어 sqltutorialdatabase
시간이 지남에 따라 오래된 데이터베이스는 불필요하거나 비어 있는 필드로 지나치게 커지는 경향이 있습니다. 일반 필드는 크게 문제가 되지 않지만 특히 수백만 개의 레코드가 있는 테이블에서 외래 키 제약 조건이 있는 필드는 데이터베이스 파일을 불필요하게 팽창시키고 적절한 인덱스를 업데이트해야 하므로 모든 삽입/업데이트/삭제 작업에서 성능 저하를 초래합니다. .

예를 들어, 100,000,000개의 레코드가 있는 테이블에서 NULL 값만 보유하는 필드의 인덱스는 크기가 약 600MB입니다(Firebird 3 데이터베이스 파일 구조의 경우 참).

아래 쿼리는 주어진 수의 고유 값만 포함하는 외래 키가 있는 필드를 찾는 데 도움이 됩니다(기본적으로 maxuniqvalues ​​변수는 비어 있거나 정확히 하나의 값을 포함하는 모든 필드를 찾기 위해 1로 설정됨). 또한 minreccnt 변수를 통해 해당 테이블의 최소 레코드 수에 대한 조건을 설정할 수 있습니다.

결과 데이터 세트에는 관계 이름, 관계의 레코드 수, 필드 이름, 값(첫 번째 값만 표시됨) 및 필드에 종속된 개체 목록 열이 포함됩니다. 나중에 필드를 삭제할 경우 후자는 많은 도움이 됩니다.

코드는 Firebird SQL 버전으로 작성되었지만 최신 SQL 서버에 쉽게 적용할 수 있습니다.

EXECUTE BLOCK
  RETURNS(
    rn VARCHAR(31),
    reccnt INTEGER,
    fkfieldname VARCHAR(31),
    val INTEGER,
    dependent VARCHAR(8192)
  )
AS
  DECLARE VARIABLE minreccnt DOUBLE PRECISION = 1000000;
  DECLARE VARIABLE maxuniqvalues DOUBLE PRECISION = 1;
BEGIN
  FOR
    SELECT
      rc.rdb$relation_name,
      CAST((1 / idx.rdb$statistics) AS INTEGER),
      idxsfk.rdb$field_name,
      (SELECT
         LIST(TRIM(d.rdb$dependent_name))
         FROM rdb$dependencies d
         WHERE 
           d.rdb$depended_on_name = rc.rdb$relation_name
           AND 
           d.rdb$field_name = idxsfk.rdb$field_name)
    FROM
      rdb$relation_constraints rc
      JOIN rdb$indices idx
        ON idx.rdb$index_name = rc.rdb$index_name
      JOIN rdb$index_segments idxs
        ON idxs.rdb$index_name = idx.rdb$index_name
        AND idxs.rdb$field_position = 0
      JOIN rdb$relation_constraints rcfk
        ON rcfk.rdb$constraint_type = 'FOREIGN KEY'
        AND rcfk.rdb$relation_name = rc.rdb$relation_name
      JOIN rdb$indices idxfk
        ON idxfk.rdb$index_name = rcfk.rdb$index_name
      JOIN rdb$index_segments idxsfk
        ON idxsfk.rdb$index_name = idxfk.rdb$index_name
        AND idxsfk.rdb$field_position = 0
    WHERE
      rc.rdb$constraint_type = 'PRIMARY KEY'
      AND
      (idx.rdb$statistics > 0 
        AND idx.rdb$statistics < (1.0 / :minreccnt))
      AND
      idxfk.rdb$statistics >= (1.0 / :maxuniqvalues)
    ORDER BY
      idx.rdb$statistics ASC
    INTO
      :rn, :reccnt, :fkfieldname, :dependent
  DO BEGIN
    EXECUTE STATEMENT 
      'SELECT FIRST 1 ' || 
      :fkfieldname || 
      ' FROM ' || 
      :rn
      INTO :val;
    SUSPEND;
  END
END

좋은 웹페이지 즐겨찾기