2009-12-31 2 views
2

서문으로, 저는 SQL Server 2005를 완전히 사용하지 않았습니다. SELECT, UPDATE, DELETE 및 INSERT 명령을 사용하는 방법을 알고 있습니다. 또한 내 로컬 PC (E8400 프로세서, 8GB DDR2-800, RAID 1의 2 x 640GB SATA-II HDD)에서 Express Edition을 사용하고 있습니다.행을 계속 추가하면 SQL Server 2005의 속도가 느려집니다.

저는 8 열로 구성된 테이블을 가지고 있는데 모두 NVARCHAR입니다 (Max)와 Null을 허용합니다. 내가 기본 키가 무엇인지 개념적으로 알고 있지만 키가 하나도 없다. (설정 방법도 모른다.)

내 VB.NET 프로그램은 존재하는 모든 단일 종목 코드에 대해 Yahoo에서 역사적인 주가 차트를 다운로드하는 것입니다. 내가 처음 추가 한 50,000 개의 행은 너무 빨랐습니다. 그 때 나는 자러 갔다. 그리고 내가 일어 났을 때 그것은 아직도 달리고 있었다 - 그러나 행 추가의 비율은 waaaaaay를 아래로 늦췄다. 나는 행 300,000 주위에 이것을 알아 차렸다. 나는 항상 행 추가 비율이 시간이 지남에 따라 일정 할 것이라고 예상했지만, 분명히 그렇게하지는 않습니다!

다른 스택 오버 플로우 관련 질문을 검색 한 결과 내 느린 문제는 저의 열악한 테이블 설정과 관련이 있다고 생각합니다. 이 경우 먼저이 문제를 해결하기 위해 어디서부터 시작해야하며, 시작하기 위해 읽을 수있는 좋은 자료가 있습니까? 내가 CSV 파일의 모든 악취 행이 반복

cmdtext = "IF NOT EXISTS(SELECT DateStamp FROM DailyPrice WHERE (DateStamp = '" +  datestamp + "' AND Ticker = '" + ticker + "')) INSERT INTO DailyPrice (Ticker,OpenPrice,ClosePrice,HighPrice,LowPrice,AdjustedClose,Volume,DateStamp) VALUES('" + ticker + "','" + openprice + "','" + closeprice + "','" + highprice + "','" + lowprice + "','" + adjustedclose + "','" + volume + "','" + datestamp + "')" 
       cmd = New SqlCommand(cmdtext, conn) 
       howmanygotinserted = cmd.ExecuteNonQuery 

:이 나는 그것이 중요한 경우 :

를 해결할 수있는 간단한 뭔가 바라고 있어요,이게 내가 추가 행을 해요 어떻게 CSV 파일 당 약 30,000 개의 행 (및 그 중 5000 개 이상)이 있습니다. 8 열

답변

7

, 모든

첫 번째 문제가있다 NVARCHAR (최대)이다. 데이터베이스는 보유하고있는 데이터 유형을 알려주고 데이터에 가장 적합한 가장 작은 데이터 유형을 선택하면 가장 잘 작동합니다. NVARCHAR (최대)는 가장 비효율적 인 선택입니다.

[기본 키]가 없습니다 (설정 방법도 알고 있지 않습니다).

그리고 두 번째 문제입니다. 모든 삽입에서 특정 열의 다른 행과 동일한 값을 가진 행을 이미 삽입했는지 확인합니다. 데이터베이스에 해당 열의 색인을 지정하지 않았으므로 매번 전체 테이블을 검사해야하므로 테이블이 커질수록 쿼리가 느려지고 느려집니다. 기존 테이블에 기본 키를 추가하려면이를 사용할 수 있습니다

ALTER TABLE table1 ADD CONSTRAINT pk_table1 PRIMARY KEY (Ticker, DateStamp) 

더 많은 정보를 원하시면 here를 참조하십시오.

+1

데이터 유형을 단독으로 고정하면 방대한 개선이 이루어졌습니다! 다음에 구현되는 기본 키를 가져올 것입니다! 나는 정말로 모두의 도움에 감사하며 모든 대답이 나를 도왔다 - 나는 그들 모두를 받아 들일 수 있었으면 좋겠다. –

1

당신은 적어도 두 가지 문제가 있습니다

  1. 테이블은 아마 적절한 인덱스를 부족;
  2. 트랜잭션 내에서 실행 중일 수 있습니다.

(Ticker, DateStamp)에 대한 색인이 있어야하며 검사 속도가 훨씬 빠릅니다. 즉, 나는 그 수표조차하지 않을 것이라고 말했다. INSERT가 실패하면 실패합니다. 더 이상.

트랜잭션 내부에서 실행 중이며 저장 지점을 커밋하거나 수행하지 않은 경우 데이터베이스에 변경 내용을 롤백 할 수 있어야하므로 행을 삽입 할 때 임시 저장소가 커집니다. 1000 행 정도를 커밋하십시오. 트랜잭션 내부에서 실행되거나 실행되지 않습니다.

이제 다음 문제는 INSERT 문을 구성하는 방법입니다. 매개 변수에 문자열 연결을 사용하지 않으려합니다. 웹 애플리케이션에서 SQL 인젝션 취약점의 큰 원인이되는 것은 나쁜 습관입니다. Insert command with parameters을보고 다음과 같이 사용하십시오.

INSERT INTO DailyPrice 
(Ticker,OpenPrice,ClosePrice,HighPrice,LowPrice,AdjustedClose,Volume,DateStamp) 
VALUES 
(@Ticker,@OpenPrice,@ClosePrice,@HighPrice,@LowPrice,@AdjustedClose,@Volume,@DateStamp) 

마지막으로 기본 키를 추가해야합니다. 이 경우 Ticker, DateStammp를 사용할 수 있지만 개인적으로 기술적 인 기본 키를 선호합니다. 즉 외부 의미가없는 기본 키를 의미합니다. 자동 증가 정수 필드는 이에 대한 가장 일반적인 예입니다. 기본 키로 (Ticker, DateSTamp)를 추가하면 앞서 언급 한 인덱스가 추가됩니다. 그것은 실제로 차이를 만드는 지수입니다.

+0

기술적 인 기본 키 사용에 대해서는 * 일반적으로 동의해야하지만,이 목적을 위해 불필요한 오버 헤드가 추가 될 수 있습니다. 다른 한편, 타임 스탬프는 특히 좋은 키를 만들지 않습니다. 관계형이 아니며 행 기반이 아닌 실제 생활에서 연속 시간 기반의 데이터를 모델링하기 때문에 관계형 데이터베이스가이 데이터를 저장하는 좋은 방법이라는 것을 완전히 확신하지는 못합니다. 하지만 망치가있을 때 ... 작동하는 것 같아요. –

+0

내 VB 앱은 로컬 전용이지만 매개 변수에 대한 귀하의 도움에 감사드립니다! 내 ASP.Net 프로그램 (이것과 관련 없음)은 절실히 필요합니다 - 매개 변수를 다시 실행합니다! –

0

먼저 테이블에 인덱스를 만들어야합니다. 문으로 인해 새 행을 추가 할 때마다 전체 표 스캔을 수행하여 기존 값을 찾습니다. 어쨌든

, 당신은 모든 삽입에 대한 특정 하여 날짜를시세 값을 가진 레코드를 확인하고 있기 때문에, 당신은 하여 날짜를시세 테이블의 기본 키, 그런 식으로 만들 수있는 데이터베이스는이 두 열을 색인화 할 것이고 IF NOT EXISTS 부분을 수행 할 필요가 없습니다 ... 이미 테이블에 주어진 키가 있으면 삽입이 실패합니다. 그러나 이것은 VB.Net 프로그램에서 예외를 발생시킬 수 있으므로 처리해야합니다.

당신이 할 수있는 또 다른 일은 열에 대한 데이터 유형, 특별히 색인 된 데이터 유형을 변경하는 것입니다. 변경할 수 있습니다. ~ nvarchar(X) (X는 일부 고정 값 (예 :) 임)을 저장할 수 있습니다. 여기에 저장할 문자열의 길이를 예측할 수 있습니다. 또한 DateStamp ~ DateTime을 변경할 수 있습니다. 데이터베이스 문제의 관점에서

+0

2 개의 기본 키를 사용할 수 있는지 전혀 몰랐습니다! 도와 줘서 고마워! –

+0

두 개의 기본 키를 가질 수 없습니다. 두 열을 사용하는 기본 키를 가질 수 있습니다. –

+0

아, 나는 오해했다. SQL 스튜디오에서 2 개의 주요 기호 (각 열에 하나씩)가 표시되어 2 개의 기본 문자를 의미합니다. 따라서 기본적으로 기본 키 (2 열의 쌍)가 고유해야합니다. –

0

대신 그 열에 DateStampTicker, 그럴 수 add a unique index 일치하는 레코드가 있는지 확인의

  • . 이렇게하면 RDBMS가 기존 레코드를 삽입하기 전에 기존 레코드를 확인하게되고 인덱스를 사용하고이를 최적화하기 때문에 현재 버전보다 훨씬 빠를 것입니다.
  • NVARCHAR(MAX)이 아닌 실제 데이터 형식을 사용하십시오. 모든 열에 대해 적절한 데이터 유형을 확인하고 varchar 열의 최대 길이를 데이터베이스에서 실제로 예상되는 값으로 줄이십시오. 이렇게하면 SELECT와 내장 인덱스 관리가 더 빨리 수행되어야합니다.
  • 매개 변수화 된 쿼리를 사용하고 단순히 매개 변수 값을 변경하면 코드가 조금 더 빠를 수 있습니다. 그렇게하면 못생긴 문자열 연결을 제거 할 수있을뿐 아니라 CSV 파일 중 하나에 "이상한"데이터가 포함되어있는 경우에도 문제가 발생하지 않습니다. ' 당신의 SQL 쿼리를 날려 버리는 문자.

그러나 CSV 리더 코드도 다시 확인합니다.실제 문제가 데이터베이스조차도 아니지만 애플리케이션에 너무 많은 메모리가 필요하고 스와핑이 발생하면 어떻게 될까요?

필자는 항상 행 추가 비율이 시간에 따라 일정 할 것으로 예상했지만, 분명히 그렇지 않습니다!

이미 알았 듯이 테이블에 많은 인덱스를 적용하면 INSERT 문이 느려질 수 있기 때문에 "악화"될 수 있습니다.

1

다른 사람들이 말한 것 외에도 한 번에 하나씩 행을 삽입한다는 점에서 문제가 있습니다. 벌크 삽입물 또는 SSIS 패키지를 사용하는 것이 훨씬 좋습니다. 행을 반복하여 많은 양의 데이터를 삽입 (또는 업데이트 또는 삭제)하지 마십시오. 데이터베이스는 많은 수의 데이터 집합을 처리하고 그렇게 할 때 훨씬 우수한 성능을 발휘하도록 설계되었습니다.