Mã đầu tiên sử dụng nvarchar (tối đa) cho tất cả các chuỗi. Điều này sẽ làm tổn thương hiệu suất truy vấn?


29

Tôi có một số cơ sở dữ liệu được tạo bằng Entity Framework Code First; các ứng dụng đang hoạt động và nói chung tôi khá hài lòng với những gì Code First cho phép tôi làm. Tôi là một lập trình viên đầu tiên, và một DBA thứ hai, bởi sự cần thiết. Tôi đang đọc về DataAttribution để mô tả thêm trong C # những gì tôi muốn cơ sở dữ liệu thực hiện; và câu hỏi của tôi là: tôi sẽ bị phạt khi ăn những nvarchar(max)chuỗi này trong bảng của mình (xem ví dụ dưới đây)?

Có một số cột trong bảng đặc biệt này; trong C # chúng được định nghĩa như vậy:

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    public string Name { get; set; }
    public string Message { get; set; }
    public string Source { get; set; }
    public DateTime Generated { get; set; }
    public DateTime Written { get; set; }

Tôi hy vọng sẽ truy vấn và / hoặc sắp xếp dựa trên Tên, Nguồn, Đã tạo và Viết. Tôi hy vọng Tên và Nguồn có độ dài 0-50 ký tự, đôi khi lên tới 150. Tôi hy vọng bảng này sẽ bắt đầu khá nhỏ (<100k hàng), nhưng tăng đáng kể theo thời gian (> 1m hàng). Rõ ràng tin nhắn có thể nhỏ hoặc lớn, và có lẽ sẽ không được truy vấn.

Những gì tôi muốn biết, có một điểm nhấn hiệu suất cho các cột Tên và Nguồn của tôi được xác định là nvarchar(max)khi tôi không bao giờ mong đợi chúng lớn hơn 150 ký tự không?


5
Có vẻ như bạn cần phải áp dụng một trong hai [MaxLength]hoặc [StringLength]thuộc tính. Một số yếu tố tiêu cực có thể có của các cột quá rộng được đề cập trong câu trả lời của @ PaulWhite tại đây
Martin Smith

3
, sử dụng varchar(max)ở mọi nơi làm tổn hại đến hiệu suất của bạn - đừng làm điều đó! Sử dụng các kiểu dữ liệu phù hợp - varchar(max) CHỈ sử dụng nếu bạn THỰC SỰ cần hơn 8000 ký tự! (Tôi chưa bao giờ thấy tên hoặc e-mail của một người dài đến thế!) - Xem Điểm sử dụng VARCHAR (n) Anymore là gì? để biết thêm thông tin
marc_s

@marc_s Liên kết tuyệt vời. Tôi biết nó làm tổn thương hiệu suất. Khi tôi xác định các bảng của riêng mình bằng SQL, tôi sử dụng varchar (n). Câu hỏi của tôi là nhiều hơn về mức độ ảnh hưởng đến hiệu suất (mặc dù tôi nhận ra rằng đã đăng không rõ ràng rõ ràng).
Nate

Câu trả lời:


24

Các mục dữ liệu nvarchar (tối đa) lớn hơn (hơn 8000 byte hoặc hơn) sẽ tràn vào lưu trữ văn bản và yêu cầu I / O bổ sung. Các mặt hàng nhỏ hơn sẽ được lưu trữ liên tiếp. Có các tùy chọn kiểm soát hành vi này - xem bài viết MSDN này để biết thêm chi tiết.

Nếu được lưu liên tiếp, không có chi phí hiệu năng I / O đáng kể; có thể có thêm chi phí CPU khi xử lý loại dữ liệu nhưng điều này có thể là nhỏ.

Tuy nhiên, việc để các cột nvarchar (tối đa) nằm xung quanh cơ sở dữ liệu mà chúng không cần thiết là hình thức khá kém. Nó có một số chi phí hiệu năng và thường kích thước dữ liệu khá hữu ích trong việc tìm hiểu bảng dữ liệu - ví dụ: cột varchar rộng 50 hoặc 100 ký tự có thể là mô tả hoặc trường văn bản tự do trong đó một trường (ví dụ) 10- 20 ký tự ling có khả năng là một mã. Bạn sẽ ngạc nhiên về ý nghĩa mà người ta thường phải suy luận từ cơ sở dữ liệu thông qua các giả định như thế này.

Làm việc trong kho dữ liệu, thường là không phải trên các hệ thống kế thừa được hỗ trợ hoặc tài liệu kém, có một lược đồ cơ sở dữ liệu dễ hiểu là khá có giá trị. Nếu bạn nghĩ rằng cơ sở dữ liệu là di sản của ứng dụng, hãy cố gắng đối xử tốt với những người sẽ kế thừa nó từ bạn.


18

Mặc dù điều này không trả lời câu hỏi cụ thể của bạn, nhưng điều đó có thể khiến bạn không cần phải đặt câu hỏi ngay từ đầu: Có thể đặt độ dài cho các biến chuỗi trong lớp mô hình C # của bạn, điều này sẽ khiến Entity Framework tạo SQL mà sử dụng loại nvarchar có độ dài cố định (ví dụ nvarchar(50)), thay vì nvarchar(max).

Ví dụ: thay vì:

public string Name { get; set; }

Bạn có thể dùng:

[StringLength(50)]
public string Name { get; set; }

Bạn cũng có thể buộc loại varcharthay vì nvarchar, nếu muốn, như sau:

[Column(TypeName = "VARCHAR")]
[StringLength(50)]
public string Name { get; set; }

Nguồn: https://stackoverflow.com/questions/7341783/entity-framework-data-annotations-set-opeslength-varchar/7341920


2
Phải tìm câu trả lời này để cho tôi biết rằng EF Core hỗ trợ loại cài đặt và độ dài cùng một lúc ( varchar(50)), nhưng EF 6 yêu cầu những gì trong câu trả lời này.
Sinjai

9

Lập chỉ mục mối quan tâm lớn nhất. Từ BOL:

Cột đó là các loại dữ liệu đối tượng lớn (LOB) ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, hoặc imagekhông thể được quy định như cột then chốt cho một chỉ mục.

Nếu bạn không thể lập chỉ mục chính xác, bạn sẽ có các truy vấn chậm. Và từ góc độ toàn vẹn dữ liệu, việc có nvarchar(max)sẽ cho phép đưa nhiều dữ liệu xấu vào một trường hơn là chỉ định giới hạn.


9

Vâng, hành vi EF mặc định trong bản đồ stringđể nvarchar(max)không phải là tốt. Trong EF 6, bạn có thể thêm quy ước tùy chỉnh của riêng mình để ghi đè hành vi này bằng ánh xạ mặc định ưa thích của riêng bạn.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<string>()
        .Configure(s => s.HasMaxLength(200).HasColumnType("varchar") );

    base.OnModelCreating(modelBuilder);
}

Ghi đè OnModelCreatingnhư trên sẽ thay đổi ánh xạ mặc định cho tất cả các chuỗi thành varchar(200).


1
Điều này không hoạt động trong EF Core 1.0
Shittu Joseph Olugbenga

the default EF behavior in mapping string to nvarchar(max) is not goodđây dường như là ý kiến ​​khái quát của bạn bạn có thể giải thích tại sao điều này là không tốt? Hoặc, bạn nghĩ, EF không phải là một khuôn khổ cho các ứng dụng kinh doanh mà bạn cần làm việc với nhiều ngôn ngữ? Bởi vì đó là loại cột mong muốn để xử lý nhiều ngôn ngữ trên cơ sở dữ liệu.
Matthias Burger

1
@MatthiasBurger nvarchar (max) là khủng khiếp cho hiệu suất, đặc biệt là trong một môi trường nhân rộng. Đó không phải là một ý kiến ​​khái quát, nó là một thực tế nổi tiếng.
dùng2966445

@ user2966445 xin lỗi, tôi nghĩ đã có sự hiểu lầm :) chắc chắn, maxthật kinh khủng. Nhưng nếu bạn muốn xử lý nhiều ngôn ngữ (và các ký tự khác nhau của chúng), bạn có cần sử dụng nvarcharkhông?
Matthias Burger

@MatthiasBurger Đúng vậy, hãy sử dụng nvarchar cho các ký tự khác nhau, nhưng toàn bộ bài đăng này là về hiệu suất và độ dài trường, chứ không phải sử dụng nvarchar so với varchar.
dùng2966445
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.