2009-07-09 43 views
27

Có tốt hơn khi sử dụng default null hoặc default "" cho trường văn bản trong MySQL?MySQL: NULL vs ""

Tại sao?

Cập nhật: Tôi biết ý nghĩa của từng điều trong số đó. Tôi quan tâm những gì là tốt hơn để sử dụng xem xét không gian đĩa và hiệu suất.

Cập nhật 2: Hey ppl! Câu hỏi là "điều gì tốt hơn để sử dụng" chứ không phải "ý nghĩa của từng" hoặc "cách kiểm tra chúng" ...

+2

Giống như hầu hết các câu hỏi "tốt hơn cho không gian đĩa và hiệu suất": tại sao bạn không chèn hàng triệu hàng bằng NULL, kiểm tra một số truy vấn và kiểm tra dung lượng đĩa? Lặp lại với "" s, và một lần nữa với một kết hợp tương đối thậm chí. Và câu trả lời là đáng tin cậy hơn nhiều so với những gì một số chàng trai ngẫu nhiên trên SO nói;) – ojrac

+1

haha, Tôi thích các ý kiến ​​cập nhật – Xeoncross

Trả lời

29

Sử dụng mặc định null. Trong SQL, null rất khác với chuỗi rỗng (""). Chuỗi rỗng đặc biệt có nghĩa là giá trị được đặt là rỗng; null có nghĩa là giá trị không được đặt hoặc được đặt thành rỗng. Ý nghĩa khác nhau, bạn thấy.

Ý nghĩa khác nhau và cách sử dụng khác nhau của chúng là lý do tại sao điều quan trọng là phải sử dụng từng câu phù hợp; số lượng không gian có khả năng được lưu bằng cách sử dụng default null như trái ngược với default "" là quá nhỏ mà nó tiếp cận sự thiếu điều kiện; tuy nhiên, giá trị tiềm năng của việc sử dụng các giá trị mặc định phù hợp như các quy tắc của quy ước là khá cao.

+1

Có, theo cách đó bạn có thể xử lý NO VALUE khác với giá trị rỗng có thể hợp lệ có thể là – AndyMcKenna

+0

Tham khảo http://stackoverflow.com/questions/1034925/is-an-overuse-of-nullable-columns-in-a-database-a-code-smell, trong đó có một số cuộc thảo luận tuyệt vời về vấn đề này. – hythlodayr

+4

Trong Oracle '' IS NULL – borjab

3

Sử dụng mọi thứ hợp lý. NULL có nghĩa là "không có giá trị có sẵn/được chỉ định", "" có nghĩa là "chuỗi rỗng".

Nếu bạn không cho phép chuỗi rỗng, nhưng người dùng không phải nhập giá trị thì NULL có ý nghĩa. Nếu bạn yêu cầu một giá trị, nhưng nó có thể trống, NOT NULL và giá trị là "" có ý nghĩa.

Và, tất nhiên, nếu bạn không yêu cầu giá trị, nhưng giá trị trống có thể được chỉ định, thì NULL có ý nghĩa.

Nhìn vào điểm hiệu quả, một bit phụ được sử dụng để xác định xem trường có là NULL hay không, nhưng đừng lo lắng về việc tối ưu hóa vi mô đó cho đến khi bạn có hàng triệu hàng.

+0

tôi muốn oracle sẽ nhận ra điều này :) –

+0

+1 Tôi đồng ý, NULL có ý nghĩa ngữ nghĩa theo tên miền kinh doanh –

+0

I sẽ không mong đợi bất kỳ sự khác biệt đáng kể về không gian đĩa hoặc hiệu suất. – davidcl

0

"" giống như hộp trống ... null giống như không có hộp nào cả.

Đây là một khái niệm khó nắm bắt ban đầu, nhưng như câu trả lời ở đây rõ ràng là nhà nước - có sự khác biệt lớn.

0

Nói chung, NULL phải biểu thị dữ liệu không có hoặc chưa được cung cấp, và do đó là giá trị mặc định tốt hơn so với chuỗi rỗng.

Đôi khi chuỗi trống là thứ bạn cần làm giá trị dữ liệu, nhưng nó hầu như không bao giờ là giá trị mặc định.

0

NULL có nghĩa là 'không có giá trị' và được xử lý đặc biệt bởi RDBMS liên quan đến điều khoản và tham gia.

"" có nghĩa là 'chuỗi rỗng' và không được xử lý đặc biệt.

Điều đó tùy thuộc vào nội dung của văn bản và cách nó thực sự được sử dụng trong truy vấn.

Ví dụ: bạn có thể có bảng câu hỏi với một số câu hỏi bắt buộc và một số câu hỏi tùy chọn.

  • Câu hỏi tùy chọn bị từ chối phải có NULL trong cột tương ứng.
  • Câu hỏi bắt buộc phải có chuỗi trống làm mặc định, vì chúng phải được trả lời. (Tất nhiên trong một ứng dụng thực tế bạn muốn nói với người dùng nhập vào một cái gì đó, nhưng tôi hy vọng bạn sẽ có được ý tưởng)
0

'' = '' mang TRUE mà thỏa mãn điều kiện WHERE

NULL = NULL sản lượng NULL mà không đáp ứng WHERE condition

Cách nào tốt hơn để sử dụng tùy thuộc vào kết quả bạn muốn nhận.

Nếu giá trị của bạn mặc định để NULL, không có truy vấn như thế này:

SELECT * 
FROM mytable 
WHERE col1 = ? 

bao giờ sẽ trở lại những giá trị này, ngay cả khi bạn vượt qua NULL cho tham số ràng buộc, trong khi truy vấn này:

SELECT * 
FROM mytable 
WHERE col1 = '' 

sẽ trả về các hàng mà bạn đã đặt thành một chuỗi rỗng.

Điều này đúng cho MySQL, nhưng không phải cho Oracle, không phân biệt giữa chuỗi trống và NULL.

Trong Oracle, truy vấn sau sẽ không bao giờ trả lại bất kỳ thứ gì.

7

Rất nhiều folks được trả lời là những gì là sự khác biệt giữa null'', nhưng OP đã yêu cầu những gì chiếm ít không gian/được nhanh hơn, vì vậy đây là đâm của tôi lúc đó:

Câu trả lời là nó phụ thuộc. Nếu trường của bạn là char(10), trường sẽ luôn mất 10 byte nếu không được đặt thành null và do đó, null sẽ chiếm ít dung lượng hơn. Phút trên cơ sở từng hàng, nhưng trên hàng triệu và hàng triệu hàng, điều này có thể tăng lên. Tôi tin rằng ngay cả một varchar(10) sẽ lưu trữ một byte (\0) như là một chuỗi rỗng, do đó, một lần nữa điều này có thể thêm lên trên bảng lớn.

Xét về hiệu suất trong truy vấn, null là về lý thuyết nhanh hơn để kiểm tra, nhưng tôi chưa thấy có thể đưa ra bất kỳ sự khác biệt đáng kể nào trên bảng được lập chỉ mục tốt. Tuy nhiên, hãy nhớ rằng bạn có thể phải chuyển đổi null sang '' ở phía ứng dụng nếu đây là lợi tức mong muốn. Một lần nữa, từng hàng, sự khác biệt là phút, nhưng nó có khả năng có thể tăng lên.

Tất cả trong tất cả đó là tối ưu hóa vi mô, do đó, nó sẽ giảm xuống tùy chọn. Sở thích của tôi là sử dụng null vì tôi muốn biết rằng không có giá trị ở đó, và không đoán nếu đó là một chuỗi trống ('') hoặc một loạt các không gian (' '). null rõ ràng về bản chất của nó. '' thì không. Vì vậy, tôi đi với null vì tôi là một loại người rõ ràng.

0

Sử dụng "". Nó đòi hỏi ít nỗ lực lập trình hơn nếu bạn có thể khẳng định rằng các cột là không null. Sự khác biệt về không gian giữa chúng là tầm thường.

44

Đối với bảng MyISAM, NULL tạo thêm một bit cho mỗi cột NULLABLE (bit rỗng) cho mỗi hàng. Nếu cột không phải là NULLABLE, thì không cần thêm chút thông tin nào nữa. Tuy nhiên, đó là đệm ra 8 bit byte, do đó bạn luôn có được 1 + mod 8 byte cho số cột NULLABLE. 1

Các cột văn bản hơi khác so với các kiểu dữ liệu khác. Đầu tiên, đối với "", mục nhập bảng chứa chiều dài hai byte của chuỗi theo sau là các byte của chuỗi và là một cấu trúc chiều dài biến thể. Trong trường hợp NULL, không cần thông tin về độ dài nhưng nó bao gồm anyways như là một phần của cấu trúc cột.

Trong InnoDB, NULLS không có khoảng trống: Chúng đơn giản không tồn tại trong tập dữ liệu. Điều này cũng đúng đối với chuỗi rỗng vì bù lệch dữ liệu không tồn tại. Sự khác biệt duy nhất là các NULL sẽ có bộ bit NULL trong khi các chuỗi rỗng sẽ không. 2

Khi dữ liệu thực sự được đặt trên đĩa, NULL và '' chiếm chính xác không gian chung trong cả hai loại dữ liệu. Tuy nhiên, khi giá trị được tìm kiếm, kiểm tra NULL là hơi nhanh hơn sau đó kiểm tra '' vì bạn không phải xem xét độ dài dữ liệu trong các phép tính của mình: bạn chỉ kiểm tra bit rỗng.

Như một kết quả của sự NULL và '' khác biệt không gian, NULL'' có NO IMPACT SIZE trừ khi cột được quy định để được nullable hay không. Nếu cột là NOT NULL, chỉ trong bảng MyISAM bạn sẽ thấy bất kỳ sự khác biệt peformance (và sau đó, rõ ràng, mặc định NULL không thể được sử dụng vì vậy nó là một câu hỏi tranh luận).

Câu hỏi thực tế sau đó tóm tắt giải thích ứng dụng của cột "không có giá trị được đặt ở đây". Nếu "" là một giá trị hợp lệ có nghĩa là "người dùng nhập vào không có gì ở đây" hoặc somesuch, sau đó mặc định NULL là thích hợp hơn khi bạn muốn phân biệt giữa NULL và "" khi một bản ghi được nhập mà không có dữ liệu trong đó.

Thông thường, mặc định thực sự chỉ hữu ích cho việc tái cấu trúc cơ sở dữ liệu, khi các giá trị mới cần có hiệu lực trên dữ liệu cũ. Trong trường hợp đó, một lần nữa, sự lựa chọn phụ thuộc vào cách dữ liệu ứng dụng được diễn giải như thế nào. Đối với một số dữ liệu cũ, NULL là hoàn toàn thích hợp và phù hợp nhất (cột không tồn tại trước đây vì vậy nó có giá trị NULL ngay bây giờ!). Đối với những người khác, "" là thích hợp hơn (thường là khi các truy vấn sử dụng SELECT * và NULL gây ra sự cố sự cố).

Trong các điều khoản chung của ULTRA (và từ quan điểm triết học) NULL mặc định cho cột NULLABLE được ưu tiên vì nó cung cấp giải thích ngữ nghĩa tốt nhất của "Không có giá trị xác định".

1 [http://forge.mysql.com/wiki/MySQL_Internals_MyISAM]

2 [http://forge.mysql.com/wiki/MySQL_Internals_InnoDB]

+0

Hey, đây là một lời giải thích tuyệt vời. Cảm ơn –

1

tôi thích null khi nó là ngữ nghĩa chính xác. Nếu có một trường địa chỉ có sẵn và người dùng không điền vào, tôi cung cấp cho nó một "". Tuy nhiên nếu có trong một thuộc tính địa chỉ trong bảng người dùng nhưng tôi đã không cung cấp cho người dùng một cơ hội để điền vào nó, tôi cung cấp cho nó một NULL.

Tôi nghi ngờ (nhưng tôi không thể xác minh) NULL và "" tạo ra nhiều sự khác biệt.

5

Tôi phát hiện ra rằng NULL vs "" là không đáng kể về mặt không gian đĩa và hiệu suất.

Lý do thực sự duy nhất tôi có thể thấy bằng cách sử dụng NULL qua '' là khi bạn có trường được đánh dấu là UNIQUE nhưng cần khả năng cho phép nhiều cột "trống".

Ví dụ: cột email trong bảng người dùng của tôi chỉ được điền nếu ai đó thực sự có địa chỉ email. Bất kỳ ai không có địa chỉ email đều nhận được NULL. Tôi vẫn có thể làm cho trường này là duy nhất bởi vì NULL không được tính là một giá trị, trong khi chuỗi rỗng '' là.

18

Từ High Performance MySQL, 3rd Edition

Tránh NULL nếu có thể. Rất nhiều bảng bao gồm cột có thể vô hiệu ngay cả khi ứng dụng không cần để lưu trữ NULL (không có giá trị), chỉ vì đó là mặc định. Thường là tốt nhất để chỉ định các cột là NOT NULL trừ khi bạn dự định lưu trữ NULL trong chúng. Khó khăn hơn để MySQL tối ưu hóa các truy vấn tham chiếu đến các cột không có giá trị, bởi vì chúng tạo chỉ mục, thống kê chỉ mục và so sánh giá trị phức tạp hơn. Cột không thể sử dụng sử dụng thêm dung lượng bộ nhớ và yêu cầu xử lý đặc biệt bên trong MySQL. Khi một cột nullable được lập chỉ mục, nó đòi hỏi một byte phụ cho mỗi mục nhập và thậm chí có thể gây ra một chỉ số kích thước cố định (chẳng hạn như chỉ mục trên một cột số nguyên) để được chuyển đổi thành một biến có kích thước trong MyISAM. Cải thiện hiệu suất từ ​​việc thay đổi cột NULL sang NOT NULL thường là nhỏ, do đó, không ưu tiên tìm và thay đổi chúng trên lược đồ hiện có trừ khi bạn biết chúng đang gây ra sự cố. Tuy nhiên, nếu bạn dự định lập chỉ mục các cột , hãy tránh làm cho chúng có thể vô hiệu nếu có thể. Có những ngoại lệ, tất nhiên. Ví dụ, đáng lưu ý rằng InnoDB cửa hàng NULL với một bit duy nhất, do đó, nó có thể được khá không gian hiệu quả cho dân cư thưa thớt dữ liệu. Tuy nhiên, điều này không áp dụng cho MyISAM.

+1

Không chuyển đổi tất cả các giá trị rỗng trong một cột chuỗi thành các chuỗi rỗng và làm cho cột KHÔNG NULL * thực sự * cải thiện hiệu suất ở bất kỳ mức độ đo lường nào? Ý tưởng rằng người ta nên tránh các cột vô hiệu vì lý do hiệu suất là một trong những điều mà tôi chưa bao giờ nghe cho đến bây giờ, và tôi ngay lập tức nghi ngờ về nó. –

+0

> Cải thiện hiệu suất từ ​​việc thay đổi cột NULL sang NOT NULL thường nhỏ –

+1

Số chính xác tôi nghĩ sẽ rất phụ thuộc vào động cơ, loại cột, kích thước cột/chỉ mục, số lượng hàng vv. Vì vậy, bạn không nên quan tâm đến điều này cho đến khi nhận được vấn đề hiệu suất thực tế với truy vấn của một số cột. –