응용 프로그램 개발자가 저지른 일반적인 데이터베이스 개발 실수는 무엇입니까?
응용 프로그램 개발자가 저지른 일반적인 데이터베이스 개발 실수는 무엇입니까?
답변:
1. 적절한 지수를 사용하지 않음
이것은 비교적 쉬운 방법이지만 여전히 항상 발생합니다. 외래 키에는 인덱스가 있어야합니다. 필드를 사용하는 WHERE
경우 색인이 있어야합니다. 이러한 인덱스는 종종 실행해야하는 쿼리를 기반으로 여러 열을 포함해야합니다.
2. 참조 무결성을 강제하지 않음
데이터베이스는 여기에서 다를 수 있지만 데이터베이스가 참조 무결성을 지원하는 경우 (모든 외래 키가 존재하는 엔터티를 가리킬 수 있음을 의미하는 경우) 사용해야합니다.
MySQL 데이터베이스에서이 실패를 보는 것이 일반적입니다. 나는 MyISAM이 그것을 지원한다고 생각하지 않습니다. InnoDB는 않습니다. MyISAM을 사용하거나 InnoDB를 사용하지만 사용하지 않는 사람들을 찾을 수 있습니다.
여기 더 :
3. 대리 (기술적) 기본 키가 아닌 자연 키 사용
자연 키는 (명시 적으로) 고유 한 외부 적으로 의미있는 데이터를 기반으로하는 키입니다. 일반적인 예로는 제품 코드, 2 자리 상태 코드 (미국), 주민등록번호 등이 있습니다. 대리 또는 기술 기본 키는 시스템 외부에서 전혀 의미가없는 키입니다. 그것들은 순수하게 엔티티를 식별하기 위해 발명되었으며 일반적으로 자동 증가 필드 (SQL Server, MySQL 등) 또는 시퀀스 (주로 Oracle)입니다.
내 의견으로는 항상 대리 키를 사용해야합니다. 이 문제는 다음과 같은 질문에서 나타났습니다.
이것은 당신이 보편적 인 동의를 얻지 못할 다소 논쟁적인 주제입니다. 자연스러운 키가 어떤 상황에서는 괜찮다고 생각하는 사람들이 있지만, 대리 키에 대한 비판은 의심 할 여지없이 불필요합니다. 당신이 저에게 묻는다면 그것은 아주 작은 단점입니다.
유고 슬라비아 와 같은 국가 도 존재하지 않을 수 있습니다 .
4. DISTINCT
작동 해야하는 쿼리 작성
ORM 생성 쿼리에서 종종이 문제가 나타납니다. 최대 절전 모드의 로그 출력을 보면 모든 쿼리가 다음과 같이 시작됩니다.
SELECT DISTINCT ...
이것은 중복 행을 반환하지 않으므로 중복 객체를 얻도록하는 약간의 지름길입니다. 때때로 사람들도이 일을하는 것을 보게 될 것입니다. 당신이 그것을 너무 많이 보면 그것은 진짜 붉은 깃발입니다. 하지 그DISTINCT
나쁜 또는 유효한 응용 프로그램이 없습니다. 그것은 (두 가지 모두에서) 수행하지만 올바른 쿼리를 작성하기위한 대리 또는 정지가 아닙니다.
에서 내가 DISTINCT 증오하는 이유 :
내 의견으로는 상황이 악화되기 시작하는 곳은 개발자가 실질적인 쿼리를 작성하고 테이블을 결합 할 때 갑자기 중복 (또는 더 많은) 행과 즉각적인 응답을 얻는 것처럼 보입니다 . 이 "문제"에 대한 그의 "해결책"은 DISTINCT 키워드를 던지고 그의 모든 문제는 사라집니다.
5. 조인에 대한 집계 선호
데이터베이스 응용 프로그램 개발자의 또 다른 일반적인 실수는 GROUP BY
조인과 비교할 때 훨씬 더 비싼 집계 (즉, 절)를 인식하지 못하는 것 입니다.
이것이 얼마나 널리 퍼져 있는지에 대한 아이디어를 제공하기 위해이 주제에 대해 여러 번 글을 썼으며 많은 찬사를 받았습니다. 예를 들면 다음과 같습니다.
첫 번째 질문 :
SELECT userid FROM userrole WHERE roleid IN (1, 2, 3) GROUP by userid HAVING COUNT(1) = 3
쿼리 시간 : 0.312 초
두번째 질문 :
SELECT t1.userid FROM userrole t1 JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2 JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3 AND t1.roleid = 1
쿼리 시간 : 0.016s
맞습니다. 내가 제안한 조인 버전 은 집계 버전보다 20 배 빠릅니다.
6. 뷰를 통해 복잡한 쿼리를 단순화하지 않음
모든 데이터베이스 공급 업체가 뷰를 지원하는 것은 아니지만 뷰를 지원하는 경우 신중하게 사용하면 쿼리를 크게 단순화 할 수 있습니다. 예를 들어 한 프로젝트 에서 CRM에 일반 당사자 모델 을 사용했습니다 . 이것은 매우 강력하고 유연한 모델링 기술이지만 많은 조인을 유발할 수 있습니다. 이 모델에는 다음이있었습니다.
예:
그래서 테드와 그의 고용주를 연결하기 위해 5 개의 테이블이 합쳐졌습니다. 모든 직원이 조직이 아닌 개인이라고 가정하고 다음과 같은 도우미보기를 제공합니다.
CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id
그리고 갑자기 원하는 데이터를 매우 간단하게 볼 수 있지만 매우 유연한 데이터 모델을 볼 수 있습니다.
7. 입력을 소독하지 않음
이것은 큰 것입니다. 이제는 PHP가 마음에 들지만 수행중인 작업을 모르는 경우 공격에 취약한 사이트를 만드는 것이 매우 쉽습니다. 작은 바비 테이블 이야기 보다 더 좋은 것은 없습니다. .
URL, 양식 데이터 및 쿠키 를 통해 사용자가 제공 한 데이터 는 항상 적대적이고 위생적인 것으로 취급해야합니다. 당신이 기대하는 것을 얻고 있는지 확인하십시오.
8. 준비된 진술을 사용하지 않음
준비된 명령문은 쿼리에서 삽입, 업데이트 및 WHERE
절에 사용 된 데이터를 뺀 후 나중에이를 제공 할 때입니다. 예를 들면 다음과 같습니다.
SELECT * FROM users WHERE username = 'bob'
vs
SELECT * FROM users WHERE username = ?
또는
SELECT * FROM users WHERE username = :username
플랫폼에 따라 다릅니다.
이 작업을 수행하여 데이터베이스가 무릎을 꿇는 것을 보았습니다. 기본적으로 최신 데이터베이스에 새로운 쿼리가 발생할 때마다 컴파일해야합니다. 이전에 본 쿼리가 발견되면 데이터베이스에 컴파일 된 쿼리와 실행 계획을 캐시 할 수있는 기회를 제공합니다. 쿼리를 많이 수행하면 데이터베이스에이를 파악하고 그에 따라 최적화 할 수 있습니다 (예 : 컴파일 된 쿼리를 메모리에 고정).
준비된 문을 사용하면 특정 쿼리가 얼마나 자주 사용되는지에 대한 의미있는 통계가 제공됩니다.
준비된 명령문은 또한 SQL 삽입 공격으로부터 사용자를 더 잘 보호합니다.
9. 충분히 정규화하지 않음
데이터베이스 정규화 는 기본적으로 데이터베이스 디자인을 최적화하는 프로세스 또는 데이터를 테이블로 구성하는 방법입니다.
이번 주에 누군가가 배열을 파기하여 데이터베이스의 단일 필드에 삽입하는 코드를 발견했습니다. 정규화하면 해당 배열의 요소를 자식 테이블의 별도 행으로 처리합니다 (즉, 일대 다 관계).
이것은 또한 사용자 ID 목록을 저장하는 최상의 방법으로 나타 났습니다 .
다른 시스템에서 목록이 직렬화 된 PHP 배열에 저장되어 있음을 보았습니다.
그러나 정규화 부족은 여러 형태로 나타납니다.
더:
10. 너무 많은 정규화
이것은 이전 시점과 모순되는 것처럼 보이지만 많은 것들과 마찬가지로 정규화는 도구입니다. 그것은 목적 자체가 아니라 목적을위한 수단이다. 많은 개발자들이 이것을 잊고 "의미"를 "끝"으로 취급하기 시작한다고 생각합니다. 단위 테스트는 이것의 대표적인 예입니다.
한때 클라이언트와 같은 거대한 계층 구조를 가진 시스템에서 일했습니다.
Licensee -> Dealer Group -> Company -> Practice -> ...
따라서 의미있는 데이터를 얻기 전에 약 11 개의 테이블을 결합해야했습니다. 정규화가 너무 멀리 취해진 좋은 예였습니다.
요컨대, 신중하고 고려 된 비정규 화는 성능상의 이점이 크지 만이를 수행 할 때는 실제로주의해야합니다.
더:
11. 전용 아크 사용
배타적 아크는 둘 이상의 외래 키를 사용하여 테이블을 만들 때 흔히 발생하는 실수입니다. 단 하나의 키만 null이 될 수 없습니다. 큰 실수. 우선 데이터 무결성을 유지하는 것이 훨씬 더 어려워집니다. 결국 참조 무결성이 있어도 둘 이상의 외래 키가 설정되는 것을 막을 수있는 것은 없습니다 (복잡한 검사 제한 조건에도 불구하고).
에서 관계형 데이터베이스 디자인에 대한 실용 가이드 :
코드를 작성하기가 어려울 수 있고 유지 보수가 더 어려울 수 있기 때문에 가능한 한 독점적 아크 구성에 대해 강력히 권고했습니다.
12. 쿼리에 대한 성능 분석을 전혀하지 않음
실용주의는 특히 데이터베이스 세계에서 지배적입니다. 원칙이 교리가되었다는 원칙을 고수한다면 실수를 저지른 것입니다. 위에서 집계 쿼리 예제를 보자. 집계 버전은 "좋아"보일 수 있지만 성능은 좋지 않습니다. 퍼포먼스 비교는 논쟁을 끝내야했지만 (그러나 그렇게하지는 않았다), 우선 잘못된 정보에 대한 견해를 내뿜는 것은 무지하고 위험하다.
13. UNION ALL, 특히 UNION 구조에 대한 과도한 의존
SQL 용어의 UNION은 일치하는 데이터 세트를 연결하기 때문에 동일한 유형 및 개수의 열을 갖습니다. 이들의 차이점은 UNION ALL은 간단한 연결이며 가능한 한 선호되는 반면 UNION은 중복 튜플을 제거하기 위해 암시 적으로 DISTINCT를 수행합니다.
DISTINCT와 같은 UNION도 그 자리에 있습니다. 유효한 응용 프로그램이 있습니다. 그러나 특히 하위 쿼리에서 많은 작업을 수행하는 경우 무언가 잘못되었을 수 있습니다. 쿼리 구성이 잘못되었거나 데이터 모델이 잘못 설계되어 이러한 작업을 수행해야 할 수 있습니다.
UNION은 특히 조인 또는 종속 하위 쿼리에 사용될 때 데이터베이스를 손상시킬 수 있습니다. 가능할 때마다 피하십시오.
14. 쿼리에서 OR 조건 사용
이것은 무해한 것처럼 보일 수 있습니다. 결국 AND는 정상입니다. 아니면 괜찮을까요? 잘못된. 기본적으로 AND 조건 은 데이터 세트를 제한 하는 반면 OR 조건 은 데이터 세트 를 늘리지 만 최적화에 적합하지는 않습니다. 특히 다른 OR 조건이 교차 할 때 옵티마이 저가 결과에 대해 DISTINCT 조작을 효과적으로 수행하도록 할 수 있습니다.
나쁜:
... WHERE a = 2 OR a = 5 OR a = 11
보다 나은:
... WHERE a IN (2, 5, 11)
이제 SQL 최적화 프로그램이 첫 번째 쿼리를 두 번째 쿼리로 효과적으로 전환 할 수 있습니다. 그러나 그렇지 않을 수도 있습니다. 하지 마십시오.
15. 고성능 솔루션에 적합하도록 데이터 모델을 설계하지 않음
이것은 정량화하기 어려운 포인트입니다. 일반적으로 그 효과에 의해 관찰됩니다. 비교적 간단한 작업에 대한 형편없는 쿼리를 작성하거나 비교적 간단한 정보를 찾기위한 쿼리가 효율적이지 않으면 데이터 모델이 좋지 않을 수 있습니다.
어떤면에서는이 점이 이전의 모든 것을 요약하지만 쿼리 최적화와 같은 작업은 종종 두 번째로 수행해야 할 때 먼저 수행된다는 것이 더 조심스러운 이야기입니다. 무엇보다도 성능을 최적화하기 전에 올바른 데이터 모델이 있는지 확인해야합니다. 크 누스가 말했듯이 :
조기 최적화는 모든 악의 근원입니다
16. 데이터베이스 트랜잭션의 잘못된 사용
특정 프로세스에 대한 모든 데이터 변경은 원자 적이어야합니다. 즉, 작업이 성공하면 완전히 수행됩니다. 실패하면 데이터는 변경되지 않습니다. - '반 완료'변경 가능성이 없어야합니다.
가장 간단한 방법은 전체 시스템 설계가 단일 INSERT / UPDATE / DELETE 문을 통해 모든 데이터 변경을 지원하도록 노력하는 것입니다. 이 경우 데이터베이스 엔진이 자동으로 수행해야하므로 특별한 트랜잭션 처리가 필요하지 않습니다.
그러나 프로세스가 데이터를 일관성있는 상태로 유지하기 위해 하나의 단위로 여러 명령문을 수행해야하는 경우 적절한 트랜잭션 제어가 필요합니다.
이와 관련하여 데이터베이스 연결 계층 및 데이터베이스 엔진이 상호 작용하는 방식의 하위 조직에도주의를 기울이는 것이 좋습니다.
17. '세트 기반'패러다임을 이해하지 못한다
SQL 언어는 특정 종류의 문제에 적합한 특정 패러다임을 따릅니다. 다양한 공급 업체별 확장에도 불구하고이 언어는 Java, C #, Delphi 등의 언어에서 사소한 문제를 해결하기 위해 어려움을 겪고 있습니다.
이러한 이해 부족은 몇 가지 방식으로 나타납니다.
명확한 책임 분담을 결정하고 각 문제를 해결하기 위해 적절한 도구를 사용하도록 노력하십시오.
개발자의 주요 데이터베이스 설계 및 프로그래밍 실수
이기적인 데이터베이스 디자인 및 사용법. 개발자는 종종 데이터의 다른 이해 관계자의 요구를 고려하지 않고 데이터베이스를 개인 영구 객체 저장소로 취급합니다. 이것은 응용 프로그램 설계자에게도 적용됩니다. 데이터베이스 설계 및 데이터 무결성이 좋지 않으면 데이터 작업을하는 타사가 어렵게되어 시스템의 수명주기 비용이 크게 증가 할 수 있습니다. 보고 및 MIS는 응용 프로그램 설계에있어 사촌이 좋지 않은 경향이 있으며 나중에 생각해야합니다.
비정규 화 된 데이터 남용. 비정규 화 된 데이터를 과도하게 사용하고 응용 프로그램 내에서 유지 관리하는 것은 데이터 무결성 문제의 레시피입니다. 비정규 화는 드물게 사용하십시오. 쿼리에 조인을 추가하지 않으려는 것이 비정규 화의 변명이 아닙니다.
SQL 작성이 두렵습니다. SQL은 로켓 과학이 아니며 실제로 업무를 잘 수행합니다. O / R 매핑 계층은 단순하고 해당 모델에 잘 맞는 95 %의 쿼리를 수행하는 데 매우 능숙합니다. 때로는 SQL이 작업을 수행하는 가장 좋은 방법입니다.
독단적 '저장 절차 없음'정책. 저장 프로 시저가 악하다고 생각하는지 여부에 관계없이 이러한 종류의 독단적 태도는 소프트웨어 프로젝트에 적용되지 않습니다.
데이터베이스 디자인을 이해하지 못합니다. 정규화는 당신의 친구이며 로켓 과학 이 아닙니다. 조인과 카디널리티는 매우 간단한 개념입니다. 데이터베이스 응용 프로그램 개발에 관여하는 경우이를 이해하지 못하는 이유는 없습니다.
저장 프로 시저에 대한 과도한 사용 및 / 또는 의존
일부 응용 프로그램 개발자는 저장 프로 시저를 중간 계층 / 프런트 엔드 코드의 직접 확장으로 간주합니다. 이것은 Microsoft 스택 개발자에게 공통적 인 특징으로 보이며 (하나이지만 성장했습니다) 복잡한 비즈니스 논리 및 워크 플로 처리를 수행하는 많은 저장 프로 시저를 생성합니다. 이것은 다른 곳에서 훨씬 잘 수행됩니다.
저장 프로시 저는 실제 기술 요소 중 일부 (예 : 성능 및 보안)를 사용해야한다는 사실이 실제로 입증 된 경우에 유용합니다. 예를 들어, 대규모 데이터 세트의 집계 / 필터링을 "데이터에 가깝게"유지하십시오.
최근에는 비즈니스 로직과 규칙의 70 %가 1400 SQL Server 저장 프로 시저 (나머지 UI 이벤트 처리기)에서 구현 된 대규모 Delphi 데스크톱 응용 프로그램을 유지 관리하고 향상시켜야했습니다. TSQL에 효과적인 단위 테스트를 도입하기가 어렵고, 캡슐화가 부족하고 도구 (디버거, 편집자)가 부족하기 때문에 이는 악몽이었습니다.
과거에 Java 팀과 함께 일하면서 나는 그 환경에서 종종 완전히 반대되는 것을 발견했습니다. Java Architect는 "데이터베이스는 코드가 아니라 데이터를위한 것"이라고 말했습니다.
요즘에는 저장된 proc를 전혀 고려하지 않는 것이 실수라고 생각하지만 유용한 이점을 제공하는 상황에서는 기본적으로 아예 사용하지 않아야합니다 (다른 답변 참조).
첫번째 문제? 장난감 데이터베이스에서만 테스트합니다. 따라서 데이터베이스가 커지면 SQL이 크롤링된다는 것을 전혀 모릅니다. 누군가가 와서 나중에 고쳐야합니다 (들리는 소리는 내 이빨입니다).
인덱스를 사용하지 않습니다.
상관 된 하위 쿼리로 인한 성능 저하
대부분의 경우 상관 된 하위 쿼리를 피하려고합니다. 하위 쿼리 내에 외부 쿼리의 열에 대한 참조가있는 경우 하위 쿼리는 상관됩니다. 이 경우 하위 쿼리는 반환 된 모든 행에 대해 한 번 이상 실행되며 상관 된 하위 쿼리가 포함 된 조건이 적용된 후 다른 조건이 적용되면 더 많은 시간이 실행될 수 있습니다.
고려 된 예와 Oracle 구문을 용서하십시오. 그러나 마지막으로 상점에서 하루에 $ 10,000 미만의 판매를 한 이후로 상점에서 고용 된 모든 직원을 찾고 싶다고 가정하십시오.
select e.first_name, e.last_name
from employee e
where e.start_date >
(select max(ds.transaction_date)
from daily_sales ds
where ds.store_id = e.store_id and
ds.total < 10000)
이 예제의 하위 쿼리는 store_id의 외부 쿼리와 상관 관계가 있으며 시스템의 모든 직원에 대해 실행됩니다. 이 쿼리를 최적화 할 수있는 한 가지 방법은 하위 쿼리를 인라인보기로 옮기는 것입니다.
select e.first_name, e.last_name
from employee e,
(select ds.store_id,
max(s.transaction_date) transaction_date
from daily_sales ds
where ds.total < 10000
group by s.store_id) dsx
where e.store_id = dsx.store_id and
e.start_date > dsx.transaction_date
이 예제에서 from 절의 쿼리는 이제 인라인 뷰 (일부 Oracle 특정 구문)이며 한 번만 실행됩니다. 데이터 모델에 따라이 쿼리는 훨씬 빠르게 실행될 것입니다. 직원 수가 증가함에 따라 첫 번째 쿼리보다 성능이 우수합니다. 첫 번째 조회는 실제로 직원 수가 적고 상점이 많으며 (아마도 많은 상점에 직원이없는 경우) daily_sales 테이블이 store_id에 색인화되어 있으면 실제로 더 잘 수행 할 수 있습니다. 이것은 가능한 시나리오는 아니지만 상관 된 쿼리가 다른 쿼리보다 성능이 더 우수한 방법을 보여줍니다.
주니어 개발자가 하위 쿼리를 여러 번 연관시키는 것을 보았으며 일반적으로 성능에 심각한 영향을 미쳤습니다. 그러나 상관 부속 조회를 제거 할 때 성능을 악화시키지 않는지 확인하기 전후에 Explain 계획 을 확인하십시오.
"실제"데이터베이스 대신 Access 사용. SQL Express , MySQL 및 SQLite 와 같은 작고 무료 인 데이터베이스가 많으 므로 훨씬 잘 작동하고 확장됩니다. 앱은 종종 예기치 않은 방식으로 확장해야합니다.
다음과 같이 추가하고 싶습니다. 고성능 코드보다 "우아한"코드 선호. 데이터베이스에 대해 가장 잘 작동하는 코드는 종종 응용 프로그램 개발자의 눈에 좋지 않습니다.
조기 최적화에 대한 넌센스를 믿습니다. 데이터베이스는 원래 디자인 및 후속 개발에서 성능을 고려해야합니다. 내 생각에 성능은 데이터베이스 디자인의 50 % (40 %는 데이터 무결성 및 마지막 10 %는 보안)입니다. 실제 사용자와 실제 트래픽이 데이터베이스에 배치되면 맨 아래에서 수행하도록 구축되지 않은 데이터베이스는 제대로 수행되지 않습니다. 조기 최적화는 최적화가 아님을 의미하지 않습니다! 그렇다고해서 쉽게 찾을 수 있기 때문에 거의 항상 제대로 수행되지 않는 코드를 작성해야한다는 의미는 아닙니다. 그것은 당신이 필요할 때까지 마지막으로 약간의 성능을 짜낼 필요가 없다는 것을 의미합니다. 데이터베이스에서 더 잘 수행되는 기능에 대해 많은 것이 알려져 있습니다.
매개 변수화 된 쿼리를 사용하지 않습니다. SQL Injection 을 중지하는 데 매우 편리합니다 .
이것은 다른 답변에서 언급 한 입력 데이터를 위생 처리하지 않는 구체적인 예입니다.
개발자가 중첩 된 select 문을 사용하거나 심지어 함수가 쿼리의 "SELECT"부분 내에서 select 문의 결과를 반환 할 때 나는 그것을 싫어합니다.
@adam도 비슷한 문제가 있음에도 불구하고 실제로 다른 곳에서는 이것을 볼 수 없다는 것에 놀랐습니다.
예:
SELECT
(SELECT TOP 1 SomeValue FROM SomeTable WHERE SomeDate = c.Date ORDER BY SomeValue desc) As FirstVal
,(SELECT OtherValue FROM SomeOtherTable WHERE SomeOtherCriteria = c.Criteria) As SecondVal
FROM
MyTable c
이 시나리오에서 MyTable이 10000 개의 행을 반환하면 결과는 쿼리마다 20001 개의 쿼리를 실행 한 것과 같습니다. 결과는 각 쿼리 행마다 초기 쿼리와 다른 테이블 각각을 한 번씩 쿼리해야했기 때문입니다.
개발자는 몇 줄의 데이터 만 반환하는 하위 개발 환경에서이 작업을 수행 할 수 있으며 하위 테이블에는 일반적으로 적은 양의 데이터 만 있지만 프로덕션 환경에서는 이러한 종류의 쿼리가 기하 급수적으로 많은 비용이들 수 있습니다 데이터가 테이블에 추가됩니다.
더 좋은 (반드시 완벽한 것은 아님) 예제는 다음과 같습니다
SELECT
s.SomeValue As FirstVal
,o.OtherValue As SecondVal
FROM
MyTable c
LEFT JOIN (
SELECT SomeDate, MAX(SomeValue) as SomeValue
FROM SomeTable
GROUP BY SomeDate
) s ON c.Date = s.SomeDate
LEFT JOIN SomeOtherTable o ON c.Criteria = o.SomeOtherCriteria
이렇게하면 데이터베이스 최적화 프로그램이 기본 테이블의 각 레코드를 다시 쿼리하지 않고 데이터를 함께 섞을 수 있으며 일반적 으로이 문제가 발생한 코드를 수정해야 할 때 일반적으로 쿼리 속도를 100 % 증가시킵니다. CPU와 메모리 사용량을 동시에 줄이면서
SQL 기반 데이터베이스의 경우 :
프로덕션 데이터베이스 내에서 일부 문제를 해결하기 전에 백업하지 않습니다.
스토어드 프로 시저의 스토어드 오브젝트 (예 : 테이블, 뷰)에서 DDL 명령 사용
저장 프로 시저 사용에 대한 두려움 또는 ORM 쿼리가 더 효율적이고 사용하기 쉬운 곳이면 어디에서나 ORM 쿼리 사용에 대한 두려움.
데이터베이스 프로파일 러 사용을 무시하면 ORM 쿼리가 최종적으로 변환되는 대상을 정확하게 알 수 있으므로 ORM을 사용하지 않을 때 로직을 확인하거나 디버깅 할 수 있습니다.
올바른 수준의 정규화를 수행하지 않습니다 . 데이터가 복제되지 않고 데이터를 필요에 따라 다른 것으로 분할하려고합니다. 또한 성능이 저하 될 정도로 정규화를 따르지 않아야 합니다.
1 - 색인이 사용되지 않은 where 절의 값에서 함수를 불필요하게 사용합니다.
예:
where to_char(someDate,'YYYYMMDD') between :fromDate and :toDate
대신에
where someDate >= to_date(:fromDate,'YYYYMMDD') and someDate < to_date(:toDate,'YYYYMMDD')+1
그리고 더 적은 범위 : 기능 색인을 필요한 값에 추가하지 마십시오 ...
2- 데이터의 유효성을 보장하기 위해 점검 제한 조건을 추가하지 않습니다. 제약 조건은 쿼리 최적화 프로그램에서 사용할 수 있으며 불변 값을 신뢰할 수 있도록하는 데 도움이됩니다. 그것들을 사용하지 않을 이유가 없습니다.
3- 순수한 게으름 또는 시간 압력으로 테이블에 정규화되지 않은 열 추가 사물은 일반적으로 이런 식으로 설계되지는 않지만이 방식으로 발전합니다. 최종 결과는 미래 진화에서 손실 된 데이터 무결성에 물렸을 때 혼란을 없애려는 수많은 작업입니다.
데이터가없는 테이블은 재 설계하기에 매우 저렴합니다. 무결성이없는 수백만 개의 레코드가있는 테이블. 따라서 열 또는 테이블을 만들 때 올바른 디자인을 수행하면 스페이드에서 상각됩니다.
4- 데이터베이스 자체는 그다지 중요하지 않지만 실제로는 성가시다. SQL의 코드 품질에 신경 쓰지 않습니다. SQL이 텍스트로 표현된다고해서 문자열 조작 알고리즘의 힙에서 논리를 숨기는 것은 괜찮습니다. 동료 프로그래머가 실제로 읽을 수있는 방식으로 텍스트로 SQL을 작성할 수 있습니다.
이전에 언급되었지만 indexes, indexes, indexes 입니다. 나는 약간의 프로파일 링 (어떤 테이블이 많은 히트를했는지 확인)을 수행 한 다음 해당 테이블에 인덱스를 추가하여 수정 된 엔터프라이즈 웹 앱의 성능이 저하되는 경우를 많이 보았습니다. 이것은 SQL 작성 지식을 많이 요구하지도 않으며 그 대가는 엄청납니다.
전염병과 같은 데이터 복제를 피하십시오. 일부 사람들은 약간의 중복이 아프지 않으며 성능을 향상시킬 것이라고 주장합니다. DBA조차도 무슨 일이 일어나고 있는지 알 수 없을 때까지 스키마를 Third Normal Form으로 고문해야한다고 말하는 것은 아닙니다. 일련의 이름, 우편 번호 또는 배송 코드를 복제 할 때마다 사본이 서로 동기화되지 않을 수 있습니다. 일어날거야. 그리고 매주 유지 보수 스크립트를 실행할 때 스스로 발 차게됩니다.
마지막으로, 명확하고 일관된 직관적 인 명명 규칙을 사용하십시오. 잘 작성된 코드를 읽을 수있는 것과 마찬가지로 좋은 SQL 스키마 또는 쿼리를 읽을 수 있어야하며 주석 없이도 실제로 수행중인 작업을 알려야 합니다. 6 개월 안에 테이블을 유지 보수해야 할 때 스스로에게 감사 할 것입니다. "SELECT account_number, billing_date FROM national_accounts"
"SELECT ACCNTNBR, BILLDAT FROM NTNLACCTS"보다 작업하기가 훨씬 쉽습니다.
20 년 동안 본 가장 흔한 실수는 미리 계획하지 않은 것입니다. 많은 개발자가 데이터베이스와 테이블을 만든 다음 응용 프로그램을 빌드 할 때 테이블을 지속적으로 수정하고 확장합니다. 최종 결과는 종종 혼란스럽고 비효율적이며 나중에 정리하거나 단순화하기가 어렵습니다.
a) 문자열의 쿼리 값 하드 코딩
b) Windows Forms 응용 프로그램의 "OnButtonPress"작업에 데이터베이스 쿼리 코드 삽입
나는 둘 다 보았다.
Scott Walz의 ' 클래식 데이터베이스 개발 실수와이를 극복하는 5 가지 방법 '이라는 비디오 링크
데이터베이스 동시성 모델과 이것이 개발에 미치는 영향을 이해하지 못합니다. 사실 후에는 색인을 추가하고 쿼리를 쉽게 조정할 수 있습니다. 그러나 핫스팟, 리소스 경합 및 올바른 작업 (방금 읽은 내용이 여전히 유효하다고 가정)을 적절히 고려하지 않고 설계된 응용 프로그램은 나중에 수정하기 위해 데이터베이스 및 응용 프로그램 계층 내에서 중요한 변경이 필요할 수 있습니다.
DBMS가 어떻게 작동하는지 이해하지 못합니다.
클러치의 작동 방식을 이해하지 않으면 스틱을 올바르게 구동 할 수 없습니다. 그리고 실제로 하드 디스크의 파일에 쓰고 있다는 것을 이해하지 않고는 데이터베이스를 사용하는 방법을 이해할 수 없습니다.
구체적으로 특별히:
클러스터형 인덱스가 무엇인지 알고 있습니까? 스키마를 설계 할 때 생각해 보셨습니까?
인덱스를 올바르게 사용하는 방법을 알고 있습니까? 인덱스를 재사용하는 방법? 취재 지수가 무엇인지 아십니까?
아주 훌륭합니다. 색인이 있습니다. 색인에서 1 행이 얼마나 큽니까? 데이터가 많을 때 인덱스가 얼마나 커 집니까? 메모리에 쉽게 맞습니까? 그렇지 않으면 인덱스로 쓸모가 없습니다.
MySQL에서 EXPLAIN을 사용한 적이 있습니까? 큰. 이제 자신에게 정직하십시오 : 당신이 본 것의 절반을 이해 했습니까? 아니, 아마 그렇지 않았을 것입니다. 고치세요.
쿼리 캐시를 이해하십니까? 쿼리를 캐싱 할 수 없게 만드는 이유를 알고 있습니까?
MyISAM을 사용하고 있습니까? 전체 텍스트 검색이 필요한 경우 MyISAM은 아무 문제가 없습니다. 스핑크스를 사용하십시오. 그런 다음 Inno로 전환하십시오.