2014-09-04 3 views
2

특정 작업을 수행 할 때마다 테이블을 업데이트해야합니다.어떤 SQL 업데이트가 더 빠르거나 더 효율적입니까?

MemberTable

  • Name varchar 60
  • Phone varchar 20
  • Title varchar 20
  • Credits int < - 모든 관련 구성원 콜 럼과 필요로하는 일 일정 업데이트
  • 등 NS 10-15 총

내가 함께이 테이블을 갱신해야 :

UPDATE Members 
SET Credits = Credits - 1 
WHERE Id = 1 

아니면 다른 테이블이 같은 두 개의 열이있는 계정이라고 만들어야합니다

계정 테이블

  • Id int
  • MemberId int < - 회원 테이블
  • Credits int

과로 업데이트로 외래 키 :

UPDATE Accounts 
SET Credits = Credits - 1 
WHERE MemberId = 1 

하나보다 빠르고 효율적으로 될 것이라고?

SQL Server가 전체 행을 읽어야 업데이트한다는 것을 읽었습니다. 그게 사실인지 모르겠습니다. 어떤 도움이라도 대단히 감사하겠습니다.

답변

1

이 질문에 직접 대답하지는 않지만 다른 대안으로이 문제를 던질 것입니다.

역사적인 거래에 관심이 있으십니까? ... 쓰기 성능의 측면에서

CREATE TABLE credit_transactions (
    member_id  int  NOT NULL 
, transaction_date datetime NOT NULL 
    CONSTRAINT df_credit_transactions_date DEFAULT Current_Timestamp 
, credit_amount int  NOT NULL 
, CONSTRAINT pk_credit_transactions PRIMARY KEY (member_id, transaction_date) 
, CONSTRAINT fk_credit_transactions_member_id FOREIGN KEY (member_id) 
    REFERENCES member (id) 
, CONSTRAINT ck_credit_transaction_amount_not_zero CHECK (credit_amount <> 0) 
); 

INSERT INTO credit_transactions (member_id, credit_amount) 
    VALUES (937, -1) 
; 

매우 간단, 어 : 모두가 될 수 있지만, 다른 미래의 독자는 경우에, 여기에 내가이 문제를 접근 할 방법 것입니다! 행 잠금이 필요하지 않습니다.

이 방법의 단점은 멤버 "잔액"을 계산하려면 약간의 계산을 수행해야한다는 것입니다.

CREATE VIEW member_credit 
    AS 
SELECT member_id 
    , Sum(credit) As credit_balance 
    , Max(transaction_date) As latest_transaction 
FROM credit_transactions 
GROUP 
    BY member_id 
; 

그러나보기를 사용하면 멋지고 단순하며 적절하게 최적화 할 수 있습니다.

지옥, 잠금 영향을 줄이려면 해당보기에서 NOLOCK을 던져서 (결정하기 전에 이에 대해 읽음) 할 수 있습니다.

TL; DR :

장점 : 빠른 쓰기 속도,

단점 가능한 거래 내역 : 느린 읽기 속도

1

실제로 나중에 방법이 더 빠릅니다. 번호 트랜잭션이 매우 거대한 경우 밀리 초 정밀도가 매우 중요한 경우에는 이렇게하는 것이 좋습니다.
또는 일부 회원에게는 크레딧이 없으므로 여기에 약간의 공간을 절약 할 수도 있습니다.

그러나 그렇지 않은 경우 테이블 구조를 표준화 된 상태로 유지하는 것이 좋습니다. 모든 계정에 항상 credit이있는 경우 표 Member의 열로 포함하는 것이 좋습니다.
더 많은 공간을 소비하는 불필요한 중간 테이블을 사용하지 않도록 노력하십시오 (모든 외래 키와 추가 ID로). 또한 스키마를 좀 더 복잡하게 만듭니다.

결국 귀하의 요구 사항에 따라 다릅니다.

+1

1. 또한 accoutns는 더 이상 검색을 수행하지 않으며 다른 테이블과 별도의 잠금을 갖게되므로 트랜잭션 처리량에 도움이됩니다. – TomTom

0

ID가 기본 키이므로 모든 dbms는 인덱스에서 키를 찾아 레코드를 가져 와서 업데이트해야합니다. 많은 성능 문제가 없어야합니다.

계정 테이블을 사용하면 완전히 동일한 액세스 방법이 사용됩니다. 그러나 당신 말이 맞습니다. 레코드 당 데이터가 적기 때문에 이미 메모리 캐시에 레코드가 있으므로 실제 읽기를 저장하는 경우가 더 많습니다.그러나, 나는 그것이 너무 자주 일어날 것을 기대하지 않을 것이다. 계정 테이블보다 회원 테이블에서 더 많은 일을 할 것입니다. 이렇게하면 캐시에 이미 구성원 레코드가있을 가능성이 높아 지므로 계정 테이블 액세스가 느려집니다.

기본 키를 사용하면 ID 인덱스에서 동일한 방법으로 걸어서 하나의 특정 레코드에 직접 액세스하기 때문에 캐시 액세스 대 물리 읽기가 유일한 차이점입니다.

계정 테이블을 사용하지 않는 것이 좋습니다. 다른 사용자가 인식 할 수없는 두 테이블 간의 1 : 1 관계로 데이터 구조를 다소 흐리게 만듭니다. 그리고 그 일로 인해 많은 것을 얻지 못할 것입니다. (언급했듯이 성능이 떨어질 수도 있습니다.)

+0

-1. 당신은 2 테이블이 잠금을 막는 것을 두 배로 막는다는 사실을 완전히 무시합니다. 잠금 세분화 ca는 테이블의 영구적 인 업데이트에 매우 중요합니다. – TomTom

+0

누군가가 버튼을 누를 때마다 크레딧을 업데이트해야 로그인 및 전화/이메일 업데이트를 제외한 회원 테이블에 약간의 조치가 표시됩니다. 감사합니다. –

+0

@TomTom : 죄송합니다. 두 경우 모두 UPDATE tablename SET Credits = Credits - 1 WHERE Id = 1'입니다. tablename은 회원 또는 계정입니다. 하나의 테이블 만 영향을받습니다. 다른 잠금 시나리오는 여기에 없습니다. –

관련 문제