SQL SELECT tốc độ int so với varchar


110

Tôi đang trong quá trình tạo một bảng và nó khiến tôi băn khoăn.

Nếu tôi lưu trữ, chẳng hạn như những chiếc ô tô có nhãn hiệu (fx BMW, Audi v.v.), nó có tạo ra sự khác biệt nào về tốc độ truy vấn không nếu tôi lưu trữ nhãn hiệu dưới dạng int hoặc varchar.

Cũng vậy

SELECT * FROM table WHERE make = 5 AND ...;

Nhanh hơn / chậm hơn

SELECT * FROM table WHERE make = 'audi' AND ...;

hoặc tốc độ sẽ nhiều hơn hoặc ít hơn như nhau?

Câu trả lời:


99

So sánh int nhanh hơn so với varchar, vì thực tế đơn giản là int chiếm ít không gian hơn so với varchars.

Điều này đúng với cả truy cập không lập chỉ mục và lập chỉ mục. Cách nhanh nhất là một cột int được lập chỉ mục.


Như tôi thấy bạn đã gắn thẻ câu hỏi postgreql, bạn có thể quan tâm đến việc sử dụng không gian của các loại ngày khác nhau:


13
Bạn đang tham khảo trang 7.4. Trong các phiên bản hiện đại, chúng chiếm 1byte + độ dài nếu bạn có <126 byte. Cũng lưu ý rằng lý do các chuỗi chậm hơn nhiều thường là do so sánh nhạy cảm đối chiếu là cực kỳ đắt - không phải là chuỗi chiếm nhiều không gian hơn. Nhưng kết quả cuối cùng là như nhau, tất nhiên.
Magnus Hagander

@Magnus - cảm ơn vì sự quan tâm. Vui lòng chỉnh sửa câu trả lời của tôi vì tôi thấy bạn có đủ điểm đại diện.
Robert Munteanu

"không phải là chuỗi chiếm nhiều không gian hơn" ... các chuỗi ký tự trên kích thước tối thiểu chiếm nhiều không gian hơn các số có độ chính xác cao, bởi vì một số (số ít) có đơn vị cố định, các chuỗi luôn là loại tổng hợp . 8 byte cho một số 64 bit 4 byte cho mỗi ký tự trong một chuỗi, bao gồm một byte độ dài hoặc cấu trúc; hoặc một nhân vật
kẻ hủy diệt

@RobertMunteanu Này Robert, xin lỗi Tôi biết đây là một bài viết cũ nhưng tôi có thể vui lòng kiểm tra ... về điều sau: để truy vấn số nguyên, tôi phải liên kết từng cột chuỗi với một bảng khác (mối quan hệ). tuy nhiên, điều đó có nghĩa là cần nhiều thao tác kết hợp hơn cho mỗi truy vấn. Làm cách nào để xác định xem sự đánh đổi này có xứng đáng không? Cảm ơn bạn!
AiRiFiEd

2
"So sánh int nhanh hơn so với varchar, vì thực tế đơn giản là int chiếm ít không gian hơn so với varchars" - điều này nói chung KHÔNG đúng . Tùy thuộc vào DBMS bạn sử dụng và các kiểu dữ liệu và chuỗi chính xác mà bạn muốn chèn, có thể hóa ra rằng các int 8 byte (giả sử) của bạn dài hơn các ascii varchars chứa một số ID văn bản có độ dài trung bình 3-4 ký tự. Vì vậy, câu trả lời này - không chính xác và thiếu bất kỳ bối cảnh cụ thể hoặc kết quả thử nghiệm - không thực sự trả lời câu hỏi. Mọi người đều biết rằng varchars được phép chiếm nhiều không gian hơn int, nhưng họ KHÔNG phải làm như vậy.
Marcin Wojnarski

36

Một số điểm chuẩn thô:

4 triệu bản ghi trong Postgres 9.x

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

Kết quả trên máy tính xách tay 8GB RAM, i7, SSD:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

Vì vậy, có vẻ như đối với thiết lập này, miễn là các chỉ mục của bạn vừa với RAM, văn bản bigint so với 16-char không có sự khác biệt về tốc độ.


6
Rất thú vị. Làm thế nào mà sự khác biệt là không đáng kể?
Chibueze Opata

18

Nó sẽ nhanh hơn một chút khi sử dụng int thay vì varchar. Quan trọng hơn đối với tốc độ là có một chỉ mục trên trường mà truy vấn có thể sử dụng để tìm các bản ghi.

Có một lý do khác để sử dụng int và đó là để chuẩn hóa cơ sở dữ liệu. Thay vì để văn bản 'Mercedes-Benz' được lưu trữ hàng nghìn lần trong bảng, bạn nên lưu trữ id của nó và lưu tên thương hiệu một lần trong một bảng riêng biệt.


Bạn có thể giải thích thêm? Ý bạn là thay vì Mercedes-Benzlưu trữ hàng nghìn lần id 1. Ví dụ bảng car_brands, cột BrandsId. Hàng Mercedes-Benz1. Và trong cột Brandsvà giá trị của bảng chính 1. Và khi nào SELECT, sau đó lúc đầu lấy Idtừ bảng car_brandsvà sau đó SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz). Hoặc một số cách tiếp cận khác?
Andris

3
@ user2118559: Vâng, đó là cách bạn sẽ lưu trữ nó. Để có được các dữ liệu bạn thường sẽ sử dụng một tham gia chứ không phải là một subquery: select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'.
Guffa

Tại sao lại ủng hộ? Nếu bạn không giải thích những gì bạn nghĩ là sai, nó không thể cải thiện câu trả lời.
Guffa

8

Chia nhỏ về hiệu suất thực tế của so sánh chuỗi so với không nổi, trong trường hợp này, bất kỳ kích thước nào không có dấu và có dấu đều không quan trọng. Kích thước thực sự là sự khác biệt thực sự về hiệu suất. Có thể là 1byte + (lên đến 126byte) so với 1,2,4 hoặc 8 byte so sánh ... rõ ràng là non-float nhỏ hơn chuỗi và float, do đó thân thiện với CPU hơn trong lắp ráp.

So sánh chuỗi với chuỗi trong tất cả các ngôn ngữ chậm hơn so với thứ mà CPU có thể so sánh trong 1 lệnh. Ngay cả khi so sánh 8 byte (64 bit) trên CPU 32 bit vẫn nhanh hơn VARCHAR (2) hoặc lớn hơn. * Một lần nữa, hãy xem lắp ráp được sản xuất (thậm chí bằng tay), cần nhiều hướng dẫn hơn để so sánh các ký tự theo ký tự so với số CPU từ 1 đến 8 byte.

Bây giờ, nhanh hơn bao nhiêu? cũng phụ thuộc vào khối lượng dữ liệu. Nếu bạn chỉ đơn giản so sánh 5 với 'audi' - và đó là tất cả những gì DB của bạn có, thì sự khác biệt kết quả là rất nhỏ mà bạn sẽ không bao giờ nhìn thấy nó. Tùy thuộc vào CPU, việc triển khai (máy khách / máy chủ, web / tập lệnh, v.v.), bạn có thể sẽ không nhìn thấy nó cho đến khi bạn đạt được vài trăm so sánh trên máy chủ DB (thậm chí có thể vài nghìn so sánh trước khi nó được chú ý).

  • Để loại bỏ tranh chấp không chính xác về so sánh băm. Bản thân hầu hết các thuật toán băm đều chậm, vì vậy bạn không được hưởng lợi từ những thứ như CRC64 và nhỏ hơn. Trong hơn 12 năm, tôi đã phát triển các thuật toán tìm kiếm cho các công cụ tìm kiếm nhiều quận và 7 năm cho các văn phòng tín dụng. Bất kỳ thứ gì bạn có thể giữ ở dạng số càng nhanh ... ví dụ như số điện thoại, mã zip, thậm chí đơn vị tiền tệ * 1000 (lưu trữ) div 1000 (truy xuất) sẽ nhanh hơn DECIMAL để so sánh.

Ozz


6

Chỉ mục hay không, int nhanh hơn rất nhiều (varchar càng dài, nó càng chậm).

Một lý do khác: chỉ mục trên trường varchar sẽ lớn hơn nhiều so với trên int. Đối với các bảng lớn hơn, nó có thể có nghĩa là hàng trăm megabyte (và hàng nghìn trang). Điều đó làm cho hiệu suất kém hơn nhiều vì chỉ đọc chỉ mục yêu cầu nhiều lần đọc đĩa.


3
Ví dụ về 5 triệu bản ghi của "audi", chẳng phải chỉ mục chỉ chứa một bản sao của chuỗi "audi" và 5 triệu số nguyên của khóa chính? Sự khác biệt về kích thước có thực sự lớn như vậy không, có thể là vchar hoặc số nguyên?
lulalala

Bạn đúng lulalala nhưng đối với một cột sẽ chứa các chuỗi ngẫu nhiên, câu trả lời là đủ công bằng.
Awais fiaz

4

Nói chung int sẽ nhanh hơn. Varchar càng dài thì nó càng chậm


3

Gợi ý: Nếu các giá trị có thể có cho trường tạo sẽ không bao giờ (hoặc hiếm khi) thay đổi, bạn có thể sử dụng ENUM như một thỏa hiệp. Nó kết hợp tốc độ tốt với khả năng đọc tốt.


1
Thật thú vị, Sự khác biệt về tốc độ giữa ENUM và int sẽ như thế nào?
googletorp

PostgresSQL có enumkiểu dữ liệu không? Tôi mặc dù nó là MySQL cụ thể.
Robert Munteanu

Postgres có ENUM, nhưng tôi không nghĩ rằng nó được triển khai theo cách hoàn toàn giống với MySQL. postgresql.org/docs/current/static/datatype-enum.html
googletorp

2
Hiệu suất khôn ngoan, ENUM nên thực hiện nhiều hơn hoặc ít hơn giống như int trong trường tìm kiếm, nhưng như varchar trong danh sách đích (vì nó phải chuyển toàn bộ chuỗi cho máy khách cho các hàng phù hợp, không chỉ int)
Magnus Hagander

1
Dưới đây là một đọc thú vị về lý do tại sao không sử dụng enum trong MySQL (chỉ cần thêm một số dầu vào lửa: D)
Wilt

1

Nếu bạn bật lập chỉ mục trên một trong hai trường, nó sẽ nhanh hơn. Đối với câu hỏi của bạn, tôi nghĩ intlà nhanh hơn varchar.


0

Hơi tương đối. Có, INT sẽ nhanh hơn, nhưng câu hỏi là liệu nó có đáng chú ý trong tình huống của bạn hay không. Các VARCHAR chỉ là một số từ nhỏ hay văn bản dài hơn? và có bao nhiêu hàng trong bảng? Nếu chỉ có một vài hàng, rất có thể nó sẽ được lưu vào bộ nhớ đệm hoàn toàn (khi được yêu cầu thường xuyên), trong trường hợp đó bạn sẽ không nhận thấy nhiều sự khác biệt. Sau đó, tất nhiên là có lập chỉ mục, điều này trở nên quan trọng hơn khi bảng phát triển. Sử dụng SSD có thể nhanh hơn so với HD với các truy vấn được tối ưu hóa. Ngoài ra, bộ điều khiển đĩa tốt đôi khi tăng tốc độ truy vấn> 10 lần. Điều này có thể để lại chỗ cho việc chỉ sử dụng VARCHAR giúp việc đọc và ghi truy vấn dễ dàng hơn (không cần viết các phép nối phức tạp) và tăng tốc độ phát triển. Tuy nhiên, những người theo chủ nghĩa thuần túy sẽ không đồng ý và luôn bình thường hóa mọi thứ.

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.