2009-06-22 35 views
19

Tôi có một quy trình được lưu trữ đang hoạt động với một lượng lớn dữ liệu. Tôi có dữ liệu được chèn vào bảng tạm thời. Dòng chảy chung của sự kiện là một cái gì đó giống nhưTạo khóa chính trên bảng tạm thời - Khi nào?

CREATE #TempTable (
    Col1 NUMERIC(18,0) NOT NULL, --This will not be an identity column. 
    ,Col2 INT NOT NULL, 
    ,Col3 BIGINT, 

    ,Col4 VARCHAR(25) NOT NULL, 
    --Etc... 

    -- 
    --Create primary key here? 
) 


INSERT INTO #TempTable 
SELECT ... 
FROM MyTable 
WHERE ... 

INSERT INTO #TempTable 
SELECT ... 
FROM MyTable2 
WHERE ... 

-- 
-- ...or create primary key here? 

Câu hỏi của tôi là khi nào là thời gian tốt nhất để tạo ra một khóa chính trên bảng #TempTable của tôi? Tôi đã giả thuyết rằng tôi nên tạo ràng buộc/chỉ mục khóa chính sau khi tôi chèn tất cả dữ liệu vì chỉ mục cần được tổ chức lại khi thông tin khóa chính đang được tạo. Nhưng tôi nhận ra rằng giả định gạch dưới của tôi có thể sai ...

Trong trường hợp có liên quan, các loại dữ liệu tôi đã sử dụng là có thật. Trong bảng #TempTable, Col1Col4 sẽ tạo thành khóa chính của tôi.

Cập nhật: Trong trường hợp của tôi, tôi đang nhân bản khóa chính của bảng nguồn. Tôi biết rằng các trường sẽ tạo nên khóa chính của tôi sẽ luôn là duy nhất. Tôi không có mối quan tâm về một bảng thay đổi không thành công nếu tôi thêm khóa chính ở cuối.

Mặc dù vậy, điều này sang một bên, câu hỏi của tôi vẫn đứng ở mức nhanh hơn giả sử cả hai sẽ thành công?

P.S. Tôi xin lỗi nếu đây là một bản sao. Nó là cơ bản đủ để nó có thể, nhưng tôi đã không thể tìm thấy bất cứ điều gì như nó.

Trả lời

14

Điều này phụ thuộc rất nhiều.

Nếu bạn tạo chỉ mục khóa chính được nhóm lại sau khi tải, toàn bộ bảng sẽ được viết lại vì chỉ mục nhóm không thực sự là chỉ mục, đó là thứ tự logic của dữ liệu. Kế hoạch thực hiện của bạn trên chèn sẽ phụ thuộc vào các chỉ mục tại chỗ khi kế hoạch được xác định và nếu chỉ mục nhóm được đặt đúng chỗ, nó sẽ sắp xếp trước khi chèn. Bạn thường sẽ thấy điều này trong kế hoạch thực hiện.

Nếu bạn tạo khóa chính là ràng buộc đơn giản, nó sẽ là chỉ mục thông thường (không được nhóm) và bảng sẽ được điền đơn giản theo thứ tự nào mà trình tối ưu hóa xác định và chỉ mục được cập nhật.

Tôi nghĩ hiệu suất tổng thể nhanh nhất (của quá trình này để tải bảng tạm thời) thường là ghi dữ liệu dưới dạng đống và sau đó áp dụng chỉ mục (không được nhóm).

Tuy nhiên, như những người khác đã lưu ý, việc tạo chỉ mục có thể không thành công. Ngoài ra, bảng tạm thời không tồn tại trong sự cô lập. Có lẽ có một chỉ số tốt nhất để đọc dữ liệu từ nó cho bước tiếp theo. Chỉ mục này sẽ cần phải được đặt tại chỗ hoặc được tạo. là nơi bạn phải cân bằng tốc độ ở đây để có độ tin cậy (áp dụng PK và bất kỳ ràng buộc nào khác trước) và tốc độ sau (có ít nhất chỉ mục nhóm nếu bạn muốn có).

+1

Thú vị. Cảm ơn bạn. Hữu ích. Bạn có thể mở rộng với một số ví dụ có lẽ? –

+0

@Cade, cho chỉ mục nhóm, bạn có nghĩa là thứ tự vật lý trên đĩa, không phải thứ tự logic (bảng không có thứ tự logic). –

+1

Không, thứ tự vật lý trên đĩa có thể là bất cứ thứ gì. Chỉ số nhóm chỉ đơn giản là dữ liệu được lưu trữ trong các lá trong một chỉ số btree thay vì trong một đống. Vẫn có thể có sự phân mảnh trong SQL Server và trên đĩa. –

3

Bạn cũng có thể tạo khóa chính trước khi chèn - nếu khóa chính nằm trên cột nhận dạng thì các lần chèn sẽ được thực hiện tuần tự và sẽ không có sự khác biệt.

+0

Tôi sẽ không sử dụng danh tính. Bạn đã đăng nội dung này trong khi tôi đang cập nhật câu hỏi của mình. Khóa chính của tôi sẽ bao gồm NUMERIC (18,0) và trường VARCHAR (25). –

+0

Các khóa chính được nhóm theo mặc định. Điều này sẽ đặt hàng tuần tự của bạn dữ liệu dựa trên giá trị PK. Tôi đồng ý với câu trả lời này, nó sẽ xảy ra trước khi bạn chèn. Cũng lưu ý: nếu bạn thêm các chỉ mục không được nhóm lại. Tạo một PK nhóm sau khi sẽ gây ra SQL Server để xây dựng lại các chỉ số không nhóm. – DBAndrew

0

Tôi không nghĩ rằng nó làm cho bất kỳ sự khác biệt đáng kể trong trường hợp của bạn:

  • hoặc là bạn trả tiền phạt một chút tại một thời điểm, với mỗi chèn đơn
  • hoặc bạn sẽ phải trả một lớn hơn hình phạt sau khi tất cả các chèn được thực hiện, nhưng chỉ một lần

Khi bạn tạo nó lên phía trước trước khi chèn bắt đầu, bạn có thể có khả năng bắt vi phạm PK như các dữ liệu đang được đưa vào, nếu giá trị không phải là PK do hệ thống tạo.

Nhưng khác hơn thế - không có sự khác biệt lớn, thực sự.

Marc

+1

chia tách mức độ và đăng nhập và nội dung? Điều này không cần phải được đưa vào tài khoản? –

1

Nếu bạn thêm khóa chính khi tạo bảng, chèn đầu tiên sẽ được miễn phí (không kiểm tra được yêu cầu.) Các chèn thứ hai chỉ có để xem nếu nó là khác nhau từ đầu tiên. Chèn thứ ba phải kiểm tra hai hàng, v.v. Các kiểm tra sẽ được tra cứu chỉ mục, bởi vì có một ràng buộc duy nhất tại chỗ.

Nếu bạn thêm khóa chính sau khi tất cả các chèn, mỗi hàng phải khớp với mỗi hàng khác. Vì vậy, tôi đoán là thêm một khóa chính sớm là rẻ hơn.

Nhưng có lẽ Sql Server có một cách thực sự thông minh để kiểm tra tính duy nhất. Vì vậy, nếu bạn muốn chắc chắn, hãy đo nó!

+0

Không nghĩ về điều đó ... điều đó tốt. –

0

Tôi không có ý định trả lời câu hỏi này vì tôi không tự tin 100% về kiến ​​thức của mình về điều này.Nhưng vì có vẻ như bạn không nhận được nhiều phản hồi ...

Sự hiểu biết của tôi là PK là chỉ mục duy nhất và khi bạn chèn từng bản ghi, chỉ mục của bạn được cập nhật và tối ưu hóa. Vì vậy ... nếu bạn thêm dữ liệu trước, sau đó tạo chỉ mục, chỉ mục chỉ được tối ưu hóa một lần.

Vì vậy, nếu bạn tự tin rằng dữ liệu của bạn sạch sẽ (không có dữ liệu PK trùng lặp) thì tôi sẽ nói chèn, sau đó thêm PK.

Nhưng nếu dữ liệu của bạn có thể có dữ liệu PK trùng lặp, tôi sẽ nói tạo PK trước, vì vậy nó sẽ ném ra ASAP.

+0

Cảm ơn bạn đã trả lời. Tôi, trên thực tế, chắc chắn rằng tôi sẽ không có một vấn đề trùng lặp ... –

1

Quan trọng hơn các cân nhắc về hiệu suất, nếu bạn KHÔNG TUYỆT ĐỐI, chắc chắn 100% rằng bạn sẽ có các giá trị duy nhất được chèn vào bảng, trước tiên hãy tạo khóa chính. Nếu không, khóa chính sẽ không được tạo.

Điều này ngăn bạn chèn dữ liệu trùng lặp/dữ liệu xấu.

+0

Đây không phải là một vấn đề đối với tôi. Tôi hiểu nó có thể là cho một số, nhưng không phải là một vấn đề ở tất cả cho tôi. –

+0

Tôi nghĩ rằng điều này có ý nghĩa chỉ vì nó thể hiện những gì bạn đang cố gắng làm rõ hơn và cho phép động cơ giúp bạn khi các giả định đã an toàn (nghĩa là chắc chắn không có dữ liệu trùng lặp nào trong bảng sau khi chèn) không còn an toàn nữa (ví dụ, do một số thay đổi trong một phần khác của cơ sở dữ liệu). – binki

6

Nếu mô hình khôi phục cơ sở dữ liệu của bạn được đặt thành đơn giản hoặc được ghi nhật ký, SELECT ... INTO ... UNION ALL có thể là giải pháp nhanh nhất. SELECT .. INTO là một hoạt động hàng loạt và hoạt động hàng loạt được ghi lại tối thiểu.

ví dụ:

-- first, create the table 
SELECT ... 
INTO #TempTable 
FROM MyTable 
WHERE ... 
UNION ALL 
SELECT ... 
FROM MyTable2 
WHERE ... 

-- now, add a non-clustered primary key: 
-- this will *not* recreate the table in the background 
-- it will only create a separate index 
-- the table will remain stored as a heap 
ALTER TABLE #TempTable ADD PRIMARY KEY NONCLUSTERED (NonNullableKeyField) 

-- alternatively: 
-- this *will* recreate the table in the background 
-- and reorder the rows according to the primary key 
-- CLUSTERED key word is optional, primary keys are clustered by default 
ALTER TABLE #TempTable ADD PRIMARY KEY CLUSTERED (NonNullableKeyField) 

Nếu không, Cade Roux đã tốt lời khuyên lại: trước hoặc sau.

1

Tôi đã tự hỏi nếu tôi có thể cải thiện một thủ tục lưu trữ rất "đắt tiền" dẫn đến một loạt các kiểm tra tại mỗi chèn trên bảng và đi qua câu trả lời này. Trong Sproc, một số bảng tạm thời được mở và tham chiếu lẫn nhau. Tôi đã thêm khóa chính vào câu lệnh CREATE TABLE (mặc dù các lựa chọn của tôi sử dụng WHERE NOT EXISTS statements để chèn dữ liệu và đảm bảo tính duy nhất) và thời gian thực hiện của tôi đã bị cắt xuống SEVERELY. Tôi khuyên bạn nên sử dụng các khóa chính. Luôn luôn ít nhất là thử nó ngay cả khi bạn nghĩ rằng bạn không cần nó.

+1

Ngữ cảnh của câu hỏi ít hơn về việc có nên tạo khóa chính hay không nhưng tại thời điểm nào là hiệu quả hơn - dân số dữ liệu trước hoặc dân số sau dữ liệu. Kết luận trước câu hỏi này là một khóa/chỉ mục đã giúp với thời gian thực hiện. –

Các vấn đề liên quan