2008-08-08 7 views
38

Tôi có nhiều bảng chỉ có dữ liệu duy nhất là cột uniqueidentifier (một hướng dẫn). Bởi vì các guids không tuần tự (và chúng được tạo phía máy khách nên tôi không thể sử dụng newsequentialid()), tôi đã tạo một chỉ mục không phải là cụm chính trên trường ID này thay vì cho các bảng một nhóm chính Chìa khóa.Bàn không có khóa chính

Tôi tự hỏi ý nghĩa của hiệu suất là gì đối với phương pháp này. Tôi đã thấy một số người cho rằng các bảng nên có một int tự động ("identity") int như là một khóa chính được phân cụm ngay cả khi nó không có ý nghĩa gì, vì nó có nghĩa là bản thân cơ sở dữ liệu có thể sử dụng giá trị đó một cách nhanh chóng tra cứu một hàng thay vì phải sử dụng dấu trang.

Cơ sở dữ liệu của tôi được hợp nhất nhân rộng trên một loạt các máy chủ, vì vậy tôi đã tránh xa các cột int nhận dạng khi chúng có chút lông để có quyền sao chép.

Suy nghĩ của bạn là gì? Bàn có nên có khóa chính không? Hoặc là ok để không có bất kỳ chỉ số nhóm nếu không có cột hợp lý để lập chỉ mục theo cách đó?

+0

Vì bạn đang thực hiện sao chép, danh tính của bạn chính xác là điều cần lưu ý rõ ràng. Tôi sẽ làm cho GUID của bạn một khóa chính nhưng nonclustered vì bạn không thể sử dụng newsequentialid. Điều đó làm tôi ngạc nhiên là khóa học tốt nhất của bạn. Nếu bạn không biến nó thành PK nhưng đặt một chỉ mục duy nhất vào nó, sớm hay muộn có thể khiến những người duy trì hệ thống không hiểu các mối quan hệ FK đúng cách đưa ra các lỗi. – HLGEM

Trả lời

32

Khi giao dịch với các chỉ mục, bạn phải xác định xem bảng của bạn sẽ được sử dụng cho mục đích gì. Nếu bạn chủ yếu chèn 1000 hàng một giây và không thực hiện bất kỳ truy vấn nào, thì chỉ mục được nhóm lại là một lần truy cập đến hiệu suất. Nếu bạn đang thực hiện 1000 truy vấn một giây thì không có chỉ mục sẽ dẫn đến hiệu suất rất kém. Điều tốt nhất cần làm khi cố gắng điều chỉnh truy vấn/chỉ mục là sử dụng Trình phân tích kế hoạch truy vấn và SQL Profiler trong SQL Server. Điều này sẽ cho bạn thấy nơi bạn đang chạy vào quét bảng tốn kém hoặc chặn hiệu suất khác.

Đối với đối số GUID vs ID, bạn có thể tìm thấy mọi người trực tuyến mà cả hai đều thề. Tôi đã luôn luôn được dạy để sử dụng GUIDs trừ khi tôi có một lý do thực sự tốt không. Jeff có một bài đăng tốt nói về các lý do sử dụng GUIDs: http://www.codinghorror.com/blog/archives/000817.html.

Giống như hầu hết mọi thứ liên quan đến phát triển, nếu bạn đang tìm cách cải thiện hiệu suất thì không có một câu trả lời đúng nào. Nó thực sự phụ thuộc vào những gì bạn đang cố gắng hoàn thành và cách bạn đang thực hiện giải pháp. Câu trả lời thực sự duy nhất là kiểm tra, kiểm tra và thử nghiệm lại các chỉ số hiệu suất để đảm bảo rằng bạn đang đáp ứng các mục tiêu của mình.

[Chỉnh sửa] @Matt, sau khi thực hiện một số nghiên cứu thêm về cuộc tranh luận GUID/ID tôi đã xem qua bài đăng này. Như tôi đã đề cập trước đây, không có câu trả lời đúng hay sai. Nó phụ thuộc vào nhu cầu thực hiện cụ thể của bạn. Nhưng đây là một số lý do khá hợp lệ để sử dụng GUID làm khóa chính:

Ví dụ: một số trang dữ liệu nhất định trong bảng dưới tranh chấp tương đối cao. Về cơ bản, những gì xảy ra là hầu hết lưu lượng truy cập trên một bảng (và do đó khóa cấp trang) xảy ra trên một khu vực nhỏ của bảng, về phía cuối. Bản ghi mới sẽ luôn đi tới điểm phát sóng này, vì IDENTITY là trình tạo số liên tiếp. Những chèn này là phiền hà vì chúng yêu cầu khóa trang Exlusive trên trang mà chúng được thêm vào (điểm phát sóng). Điều này có hiệu quả serializes tất cả các chèn vào một bảng nhờ cơ chế khóa trang. Mặt khác, NewID() không bị các điểm nóng. Các giá trị được tạo ra bằng cách sử dụng hàm NewID() chỉ là tuần tự cho các cụm chèn ngắn (trong đó hàm được gọi rất nhanh, chẳng hạn như trong chèn nhiều hàng), điều này làm cho các hàng được chèn ngẫu nhiên trên các trang dữ liệu của bảng của tất cả ở cuối - do đó loại bỏ một điểm nóng từ chèn.

Ngoài ra, do chèn được phân phối ngẫu nhiên, cơ hội chia tách trang được giảm đáng kể.Trong khi một trang chia nhỏ ở đây và không có quá xấu, các hiệu ứng sẽ tăng lên nhanh chóng. Với IDENTITY, trang Fill Factor là khá vô dụng như một cơ chế điều chỉnh và cũng có thể được đặt thành 100% - các hàng sẽ không bao giờ được chèn vào bất kỳ trang nào nhưng trang cuối cùng. Với NewID(), bạn thực sự có thể sử dụng Fill Factor làm công cụ cho phép hiệu suất. Bạn có thể thiết lập Fill Factor thành một mức xấp xỉ sự tăng trưởng khối lượng ước tính giữa các chỉ số xây dựng lại, và sau đó lên kế hoạch xây dựng lại trong giờ cao điểm bằng cách sử dụng dbcc reindex. Điều này có hiệu quả làm chậm các lần truy cập hiệu suất của việc chia tách trang cho đến thời gian cao điểm.

Nếu bạn thậm chí nghĩ bạn có thể cần phải kích hoạt sao chép cho bảng được đề cập - sau đó bạn cũng có thể làm cho PK là bộ định danh duy nhất và gắn cờ trường guid là ROWGUIDCOL. Việc nhân rộng sẽ yêu cầu một trường guid có giá trị duy nhất với thuộc tính này và nó sẽ thêm một trường nếu không tồn tại. Nếu một trường phù hợp tồn tại, sau đó nó sẽ chỉ sử dụng một trong đó thats.

Tuy nhiên, một lợi ích rất lớn cho việc sử dụng GUID cho PKS là một thực tế rằng giá trị thực sự là đảm bảo độc đáo - không chỉ trong số tất cả các giá trị được tạo ra bởi máy chủ này, nhưng tất cả các giá trị được tạo ra bởi tất cả máy tính - cho dù đó là của bạn máy chủ db, máy chủ web, máy chủ ứng dụng hoặc máy khách. Khá nhiều ngôn ngữ hiện đại có khả năng tạo ra một guid hợp lệ ngay bây giờ - trong .NET bạn có thể sử dụng System.Guid.NewGuid. Điều này rất tiện dụng khi xử lý các bộ dữ liệu tổng thể chi tiết được lưu trong bộ nhớ cache nói riêng. Bạn không phải sử dụng các kế hoạch khóa tạm thời điên chỉ để liên kết các hồ sơ của bạn với nhau trước khi chúng được cam kết. Bạn chỉ cần tìm một Guid hoàn toàn hợp lệ mới từ hệ điều hành cho mỗi giá trị khóa vĩnh viễn của mỗi bản ghi mới tại thời điểm bản ghi được tạo ra.

http://forums.asp.net/t/264350.aspx

+2

Đọc của Kimberly Tripp [GUIDs là Primary và/hoặc clustering key] (http://sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx) và [Disk không gian giá rẻ - đó là ** KHÔNG ** điểm!] (http://www.sqlskills.com/BLOGS/KIMBERLY/post/Disk-space-is-cheap.aspx) và rất nhiều bài đăng trên blog tuyệt vời của cô ấy - cô ** rõ ràng ** chỉ cho thấy ý tưởng xấu của một khóa phân cụm trên cột GUID là như thế nào. Ngoài ra - các điểm nóng là một huyền thoại bị gỡ rối lâu - không còn là vấn đề nữa sau khi SQL Server 6.5 .... –

+1

Hấp dẫn. Tôi sẽ xem xét tùy chọn "phân chia trang và lập lại chỉ mục" nếu hiệu suất trở thành vấn đề. Cảm ơn vì điều đó. –

0

Tôi cũng đã luôn nghe nói rằng có int tự động tăng là tốt cho hiệu suất ngay cả khi bạn không thực sự sử dụng nó.

7

Mấu chốt chính phục vụ ba mục đích:

  • chỉ ra rằng cột (s) nên là duy nhất
  • chỉ ra rằng cột (s) nên không null
  • ghi rõ ý định rằng đây là số nhận dạng duy nhất của hàng

Hai loại đầu tiên có thể được xác định theo nhiều cách, như bạn đã làm.

Lý do thứ ba là tốt:

  • đối với con người, để họ có thể dễ dàng nhận thấy ý định của bạn
  • cho máy tính, do đó, một chương trình mà có thể so sánh hoặc xử lý bảng của bạn có thể truy vấn cơ sở dữ liệu cho khóa chính của bảng.

Khóa chính không phải là trường số tăng tự động, vì vậy tôi có thể nói rằng bạn nên chỉ định cột guid làm khóa chính.

+0

Nó chắc chắn không phải là một ý tưởng tốt để có một cột guid như một khóa chính, bởi vì các khóa chính được nhóm lại và guids là ngẫu nhiên. Điều đó có nghĩa là bất cứ khi nào bạn chèn một hàng mới, bảng của bạn về cơ bản sẽ được cấu trúc lại trên đĩa. Mọi người thường khuyên rằng các khóa chính nên được tuần tự, các loại ngày càng tăng để mỗi hàng mới được tacked vào cuối bảng. –

+0

Một khóa chính là theo mặc định được hỗ trợ bởi một chỉ số nhóm nhưng nó có thể được loại bỏ (chỉ mục nhóm). –

+0

@MattHamilton tái "... không phải là một ý tưởng tốt để có một cột guid như một khóa chính, bởi vì các khóa chính được nhóm lại và guids là ngẫu nhiên" để khắc phục điều này, bạn có thể sử dụng chức năng "newsequentialid()" trên SQL 2005/2008 chỉnh sửa: tìm thấy các điều kiện tiên quyết [CodingHorror bài] (http://www.codinghorror.com/blog/archives/000817.html) mà nói về điều này ;-) –

1

Khóa chính không cần phải là trường tự động gia tăng, trong nhiều trường hợp điều này có nghĩa là bạn đang làm phức tạp cấu trúc bảng của bạn. Thay vào đó, Khóa chính phải là tập hợp các thuộc tính tối thiểu (lưu ý rằng hầu hết DBMS sẽ cho phép khóa chính kết hợp) nhận dạng duy nhất một bộ dữ liệu.

Về mặt kỹ thuật, nó phải là trường mà mọi trường khác trong bộ dữ liệu hoàn toàn phụ thuộc vào chức năng. (Nếu bạn không cần bình thường hóa).

Trên thực tế, vấn đề hiệu suất có thể có nghĩa là bạn nên kết hợp bảng và sử dụng một trường incrementing, nhưng tôi dường như nhớ lại điều gì đó về sớm tối ưu hóa vốn là xấu ...

6

Chỉ cần nhảy vào, vì Matt mồi cho tôi một chút .

Bạn cần hiểu rằng mặc dù chỉ mục nhóm được đặt trên khóa chính của bảng theo mặc định, rằng hai khái niệm là riêng biệt và cần được xem xét riêng. CIX chỉ ra cách dữ liệu được lưu trữ và được NCIX giới thiệu, trong khi PK cung cấp tính duy nhất cho mỗi hàng để thỏa mãn các yêu cầu LOGICAL của một bảng.

Bảng không có CIX chỉ là Heap. Một bảng không có PK thường được coi là "không phải là bảng". Tốt nhất là bạn nên hiểu rõ cả hai khái niệm PK và CIX để bạn có thể đưa ra quyết định hợp lý trong thiết kế cơ sở dữ liệu.

Rob

3

Không ai trả lời câu hỏi thực tế: là những gì ưu điểm/nhược điểm của một bảng với NO PK NOR một clustered index. Theo ý kiến ​​của tôi, nếu bạn tối ưu hóa cho chèn nhanh hơn (đặc biệt là chèn hàng loạt gia tăng, ví dụ: khi bạn tải dữ liệu hàng loạt vào một bảng không trống), bảng đó: với chỉ số nhóm KHÔNG, KHÔNG CÓ ràng buộc, KHÔNG CÓ Khóa Ngoại, KHÔNG CÓ Mặc định và NO Primary Key, trong một cơ sở dữ liệu với Simple Recovery Model, là tốt nhất. Bây giờ, nếu bạn muốn truy vấn bảng này (trái ngược với quét toàn bộ nó), bạn có thể muốn thêm một chỉ mục không được phân cụm không cần thiết nhưng cần giữ chúng ở mức tối thiểu.

+0

Trên thực tế, đây là ** sai ** - như Kimberly Tripp (Nữ hoàng lập chỉ mục) hiển thị rõ ràng: có chỉ số ** nhóm ** tốt ** sẽ tăng ** hiệu suất INSERT! http: // sqlskills.com/BLOGS/KIMBERLY/post/The-Clustered-Index-Debate-Continues.aspx –

+0

Tôi sẽ không gọi đó là _clearly_ hiển thị :) Cô ấy nói về các nguyên tắc chung, không sao lưu tuyên bố của cô ấy, vâng, bất cứ điều gì, trong khi tôi nói về một kịch bản rất cụ thể mà tôi gặp phải trong thực tế của mình: chèn hàng loạt hàng trăm triệu bản ghi vào một bảng không trống, sau đó không bao giờ được cập nhật hoặc truy cập ở chế độ đọc ngẫu nhiên mà chỉ quét toàn bộ. Tôi cho rằng có thể có nhiều yếu tố chơi hơn chỉ số mặc dù. Luôn kiểm tra những đứa trẻ tối ưu hóa của bạn. – zvolkov

0

Vì bạn đang thực hiện sao chép, danh tính của bạn chính xác là điều cần biết rõ ràng. Tôi sẽ làm cho GUID của bạn một khóa chính nhưng nonclustered vì bạn không thể sử dụng newsequentialid. Điều đó làm tôi ngạc nhiên là khóa học tốt nhất của bạn. Nếu bạn không biến nó thành PK nhưng đặt một chỉ mục duy nhất vào nó, sớm hay muộn có thể khiến những người duy trì hệ thống không hiểu các mối quan hệ FK đúng cách đưa ra các lỗi.