Trong bài viết này, chúng ta sẽ xem xét toán tử bitwise là gì và liệu việc sử dụng chúng có còn phù hợp trong thời đại điện toán hiện đại này hay không
Trường hợp sử dụng ví dụ
Các toán tử bitwise được liệt kê ở đây, nhưng để thực sự đưa ví dụ về nhà, chúng tôi sẽ chỉ tập trung vào một. bitwise và [
SELECT * FROM user WHERE id = 5 AND 512 & permissions
2]. Một ví dụ làm cho nó nhấp chuột cho tôi. Vì vậy, đó là những gì chúng ta sẽ làm - đi thẳng vào một ví dụHãy tưởng tượng bạn có một trang web mà một người dùng nhất định có thể có các quyền cụ thể. Ví dụ, một tạp chí như SitePoint
- một tác giả có thể CRUD bản nháp và chỉnh sửa hồ sơ của họ
- một biên tập viên có thể, ngoài những điều trên, các bản nháp CRUD và các bài đăng đã hoàn thành cũng như hồ sơ tác giả CRUD
- quản trị viên có thể, ngoài những điều trên, thêm quyền của quản trị viên
Vì một người dùng có thể có nhiều quyền nên có một số cách xác định quyền trong cơ sở dữ liệu và hệ thống sử dụng nó
Tham gia đôi
Thêm vai trò, thêm quyền, gắn quyền vào vai trò trong bảng tham gia, sau đó tạo một bảng tham gia khác và liên kết một số vai trò với một số người dùng
Cách tiếp cận này tạo thêm bốn bảng
- quyền
- vai trò
- permissionsroles
- rolesusers
Khá nhiều chi phí. Hãy tưởng tượng bạn phải thường xuyên chỉnh sửa hoặc liệt kê chúng trong ứng dụng trong một số danh sách thường xuyên truy cập. Chỉ bộ nhớ đệm nặng mới cứu được ứng dụng này khỏi bị sập khi tải nặng
Tuy nhiên, một lợi thế là bằng cách xác định vai trò thực sự tốt với các quyền phức tạp, bạn chỉ cần gắn người dùng vào các vai trò và bạn ổn – điều đó giúp bảng tham gia nhẹ nhàng và nhanh chóng
Tham gia đơn
Thêm quyền, thêm bảng tham gia, đính kèm một số quyền cho một số người dùng
Cách tiếp cận này tạo ra hai bảng phụ
- quyền
- permissionsusers
Ít chi phí hơn nhiều so với ví dụ trước, nhưng bạn có nhiều mục hơn trong bảng tham gia vì người dùng có thể có RẤT NHIỀU quyền [riêng CRUD để soạn thảo có 4 quyền]. Với nhiều người dùng và nhiều quyền, bảng này có thể trở nên nặng nề nhanh chóng
cột giẫm đạp
Thêm một cột vào bảng người dùng cho mỗi quyền, sau đó đặt kiểu dữ liệu của nó là tinyint[1] [về cơ bản là boolean] để kiểm tra quyền là “bật” hoặc “tắt”
Đặt quyền cho người dùng sau đó sẽ giống như thế này
UPDATE `users` SET `editProfile` = 1, `deleteProfile` = 0, `createDraft` = 1, `publishDraft` = 0 ... WHERE `id` = 5
Cách tiếp cận này không thêm bảng bổ sung, nhưng mở rộng bảng thành chiều rộng khổng lồ một cách không cần thiết và yêu cầu sửa đổi cơ sở dữ liệu mỗi khi thêm quyền mới. Đó là một cách tiếp cận tốt khi bạn biết mình sẽ có nhiều nhất hai hoặc ba quyền trong tương lai gần, nhưng không nên sử dụng cho bất kỳ mục đích nào khác
Tuy nhiên, vì danh sách các cột, khi nhìn từ xa, giống như một số nhị phân [1010], nên cách tiếp cận này là một cách tuyệt vời để chuyển sang một…
Phương pháp Bitwise
Trước khi chúng ta tìm hiểu sâu hơn về cách tiếp cận này, chúng ta hãy tham gia một khóa học cấp tốc về nhị phân
Số nhị phân
Tất cả các máy tính lưu trữ dữ liệu dưới dạng nhị phân. 0 hoặc 1. Vì vậy, số 14 thực sự được lưu trữ dưới dạng. 1110. Làm thế nào vậy?
Các số nhị phân được đánh giá từ phải sang trái khi tính toán giá trị của chúng, giống như số thực. Vậy số 1337 có nghĩa là
- 1x7
- + 3x10
- + 3x100
- + 1x1000
Bởi vì mỗi chữ số trong hệ thập phân [cơ số 10] được nhân với 10. Cái đầu tiên là 1, cái tiếp theo là 10, cái tiếp theo sau 100, 1000 tiếp theo, v.v.
Trong hệ nhị phân, cơ số là 2, vì vậy mỗi chữ số được nhân với 2. Do đó, số 1110 là
- 0x1
- + 1x2
- + 1x4
- + 1x8
Đó là 2 + 4 + 8, tức là 14
Vâng, thật đơn giản để chuyển đổi số nhị phân sang số thập phân
Vì vậy, khi chúng tôi xem xét các cột quyền của mình từ trước 1010, điều đó cũng có thể được coi là số 10 được viết ở dạng nhị phân. Hmm, có lẽ chúng ta đang làm gì đó ở đây
Nếu chúng ta có quyền 1010, điều đó có nghĩa là bit thứ 2 và thứ 4 được đặt, trong khi bit thứ nhất và thứ ba thì không [vì chúng là 0]
Theo cách nói nhị phân, chúng tôi thực sự nói rằng bit thứ 0 và thứ 2 không được đặt, bởi vì chúng được tính từ 0, giống như các mảng. Điều này là do số thứ tự của chúng [thứ 1, thứ 2, thứ 3] tương ứng với số mũ của chúng. Bit thứ 0 thực sự là 2 lũy thừa của 0 [2^0] bằng 1. Bit đầu tiên là 2 lũy thừa của 1 [2^1] là 2. Thứ 2 là 2 bình phương [2^2] bằng 4, v.v. Bằng cách đó, tất cả đều rất dễ nhớ
Vậy điều này giúp chúng ta như thế nào?
Phương pháp Bitwise
Chà, bằng cách xem xét các quyền từ xa, chúng ta có thể biểu thị trạng thái của tất cả các cột cùng một lúc bằng một số nhị phân. Nếu chúng ta có thể biểu diễn tất cả các cột cùng một lúc bằng một số nhị phân duy nhất, điều đó có nghĩa là chúng ta cũng có thể biểu thị nó bằng một số nguyên duy nhất khi dịch sang số thập phân
Nếu chúng tôi có một cột
SELECT * FROM user WHERE id = 5 AND 512 & permissions
3 duy nhất chứa giá trị SELECT * FROM user WHERE id = 5 AND 512 & permissions
4, bây giờ chúng tôi sẽ biết rằng đây thực sự là SELECT * FROM user WHERE id = 5 AND 512 & permissions
5 và chúng tôi sẽ biết rằng chúng tôi có ba trong số bốn quyền. Nhưng cái nào 3 của chúng tôi trong số 4?Hãy tưởng tượng ánh xạ quyền sau đây
THAY ĐỔI GIẤY PHÉP HỒ SƠ TẠO HỒ SƠ CHỈNH SỬA HỒ SƠ DELETEDRAFT CREATEDRAFT EDITDRAFT DELETEDRAFT PUBLISHFINISHED EDITFINISHED DELETE5122561286432168421Số 14 trong hệ nhị phân là 1110, nhưng số lượng số 0 ở bên trái không quan trọng, vì vậy chúng ta có thể đệm nó cho đến khi đạt đến số lượng quyền trong bảng. 0000001110. Đây vẫn là 14, chỉ đại diện cho các quyền từ bảng trên. Đối với tất cả ý định và mục đích, 0000001110 === 1110
Theo đó, chúng tôi thấy rằng tài khoản có quyền của
SELECT * FROM user WHERE id = 5 AND 512 & permissions
4 có quyền. SELECT * FROM user WHERE id = 5 AND 512 & permissions
0, SELECT * FROM user WHERE id = 5 AND 512 & permissions
1 và SELECT * FROM user WHERE id = 5 AND 512 & permissions
2. Được cấp, không chính xác đại diện cho thiết lập quyền trong thế giới thực, nhưng đây chỉ là một ví dụ mà qua đó chúng ta có thể ngoại suy rằng nếu một người có 1111111111, thì họ sẽ có TẤT CẢ các quyền [có thể là người dùng quản trị viên]. Trong số thập phân, đây là 1023. Vì vậy, ai đó có giá trị SELECT * FROM user WHERE id = 5 AND 512 & permissions
3 trong cột SELECT * FROM user WHERE id = 5 AND 512 & permissions
3 là người có tất cả các quyềnNhưng làm cách nào để kiểm tra điều này trong mã của chúng tôi?
Đó là những gì toán tử bitwise dành cho - đặc biệt là ký hiệu đơn và
SELECT * FROM user WHERE id = 5 AND 512 & permissions
2, còn được gọi là bitwise vàMySQL hỗ trợ nó như vậy
SELECT * FROM user WHERE id = 5 AND 512 & permissions
Điều này dịch theo nghĩa đen là “chọn tất cả người dùng có ID 5, những người cũng có bit 512 của cột
SELECT * FROM user WHERE id = 5 AND 512 & permissions
3 được đặt thành 1″. Bạn sẽ kiểm tra các bit khác bằng cách thay đổi giá trị của chúng. 256, 128, 64, 32, 16, 8, 4, 2 hoặc 1Ghi chú bên lề [không bắt buộc] “hãy tìm hiểu về kỹ thuật”
Bỏ qua phần được chia này nếu bạn không muốn biết cách thức hoạt động của toán tử này hoặc các toán tử tương tự mà chỉ muốn tiếp tục với ví dụ
Khi chúng tôi nói
SELECT * FROM user WHERE id = 5 AND 512 & permissions
7, chúng tôi đang tìm kiếm phần sau AND là TRUE, bởi vì đó là cách hoạt động của các truy vấn SQL – chúng đánh giá các điều kiện và trả về những hàng trả về đúng đối với các yêu cầuDo đó,
SELECT * FROM user WHERE id = 5 AND 512 & permissions
8 phải đánh giá là true. Chúng tôi biết rằng bất kỳ giá trị khác 0 nào, có thể là số nguyên, boolean có nội dung “true” hoặc một chuỗi không trống, đều thực sự được coi là “true”. Vì vậy, 512 là đúng. 1 là đúng. 0 là sai. 128 là đúng. Vân vân512 là số nguyên cơ số 10 và
SELECT * FROM user WHERE id = 5 AND 512 & permissions
3 là cột có thể chứa số nguyên cơ số 10. Bitwise và thực sự nhìn vào mặt cắt ngang của hai số này và trả về các bit được đặt [1] trong cả hai số đó. Vì vậy, nếu số 512 là 1000000000 và nếu giá trị quyền là 1023 thì khi được chuyển đổi thành nhị phân đó là 1111111111. Mặt cắt ngang của các giá trị đó trả về 1000000000 vì chỉ bit ngoài cùng bên trái được đặt ở cả hai số. Khi chúng tôi chuyển đổi lại số này thành số thập phân, đó là 512, được coi là if [1023 & 1] {
}
0Đây thực sự là các toán tử logic, không phải số học, ở chỗ chúng kiểm tra tính trung thực dựa trên một điều kiện. Nếu chúng ta có các số 1110 và 1010, thì đây là những gì chúng tạo ra với các toán tử bitwise khác nhau
–&. ^~Toán hạng A1110111011101110Toán hạng B101010101010/Kết quả1010111001000001
2 trả về một số nhị phân trong đó tất cả các bit được đặt được đặt trong cả hai toán hạngSELECT * FROM user WHERE id = 5 AND 512 & permissions
2 trả về một số nhị phân với tất cả các bit được đặt trong một trong hai toán hạngif [1023 & 1] { }
3 trả về một số nhị phân với tất cả các bit được đặt được đặt ở một trong hai toán hạng, nhưng không phải cả haiif [1023 & 1] { }
4 chỉ trả về điều ngược lại – tất cả những giá trị không được đặt trong toán hạng ban đầu hiện đã được đặtif [1023 & 1] { }
Ngoài ra còn có các toán tử dịch chuyển bitwise. dịch chuyển trái ________ 85 và dịch chuyển phải ________ 86. Những giá trị này thay đổi đáng kể giá trị của các số nhị phân bằng cách di chuyển tất cả các bit đã đặt sang phải hoặc trái theo đúng nghĩa đen. Việc sử dụng chúng trong ngữ cảnh của chúng tôi còn nhiều nghi vấn, vì vậy chúng tôi sẽ không đề cập đến chúng ở đây
Và trong PHP, chúng ta có thể kiểm tra xem một bit có được đặt như vậy không
________số 8Nhưng điều này thực sự rất khó để giải mã – chỉ nhìn vào những con số thô thì không thể đọc hoặc hiểu được. Vì vậy, trong PHP, tốt hơn là sử dụng các hằng xác định quyền dưới dạng bit và tìm nạp giá trị số nguyên của quyền từ cột. Sau đó, bạn kết thúc với một cái gì đó như thế này
SELECT * FROM user WHERE id = 5 AND 512 & permissions
5Ở đây, chúng tôi giả sử rằng chúng tôi đã định nghĩa một lớp
if [1023 & 1] {
}
7 và tải các hằng số như thế nàySELECT * FROM user WHERE id = 5 AND 512 & permissions
7Đột nhiên, bạn có một cách thực sự dễ dàng để lưu trữ nhiều quyền cho mỗi người dùng mà không cần sử dụng thêm bảng và tạo chi phí không cần thiết
Vậy làm cách nào để chúng tôi lưu trữ điều này trong cơ sở dữ liệu khi quyền thay đổi? . Một người có thể
if [1023 & 1] {
}
8 và SELECT * FROM user WHERE id = 5 AND 512 & permissions
2 có quyền 1 và 2, theo các hằng số ở trên. Do đó, để lưu quyền của họ, bạn chỉ cần tính tổng [1+2=3] và lưu 3 vào cột SELECT * FROM user WHERE id = 5 AND 512 & permissions
3. Không có cách nào khác để lấy số 3 bằng các tổ hợp nhị phân – số 3 không thể được biểu diễn dưới dạng nhị phân theo bất kỳ cách nào khác ngoài 0011 – vì vậy bạn có thể chắc chắn 100% rằng số 3 luôn có nghĩa là người dùng có quyền 1 và quyền 2, Điều này có vẻ quá đơn giản và thiết thực phải không?
Hãy cẩn thận
Có hai cảnh báo chính
- Bạn cần lưu ý sử dụng lũy thừa của 2 khi tính giá trị bit của quyền tiếp theo. Vì vậy, nếu bạn cần thêm một quyền mới, bạn không thể tùy ý chọn 543 nếu bạn đã có 512 – nó sẽ phải là 1024. Điều này trở nên phức tạp hơn một chút khi các con số lớn hơn
- Vì máy tính của chúng tôi đang chạy hệ điều hành 64 bit trên CPU 64 bit [hầu hết – một số thậm chí còn bị kẹt trên 32 bit. ], điều đó có nghĩa là một số chỉ có thể có tối đa 64 bit. Điều này có nghĩa là bạn chỉ có thể lưu trữ hoán vị tối đa 64 quyền đối với một người dùng nhất định. Đối với các trang web vừa và nhỏ, điều này là khá đủ, nhưng trên các trang web lớn, điều này có thể trở thành một vấn đề. Giải pháp ở đây là sử dụng các cột khác nhau cho các bối cảnh quyền khác nhau [______151,
52, v.v. ]. Sau đó, mỗi cột đó có thể chứa các hoán vị của 64 quyền riêng, đủ cho cả những trang web đòi hỏi khắt khe nhấtSELECT * FROM user WHERE id = 5 AND 512 & permissions
Sự kết luận
Hoạt động bitwise chắc chắn vẫn có một vị trí trong lập trình hiện đại. Mặc dù có thể phản trực giác khi sử dụng một thứ gì đó có vẻ phức tạp [thực sự không phải vậy - nó gần như không quen thuộc như các bảng tham gia ngày nay], phương pháp này mang lại nhiều lợi ích - không kém phần quan trọng là tăng hiệu suất đáng kể, cả về dữ liệu
Các gói như những gói được trình bày ở đây chắc chắn làm cho mọi thứ trở nên đơn giản, nhưng chỉ khi bạn chưa biết về các lựa chọn thay thế đơn giản hơn như những gói được trình bày ở trên
Bạn cảm thấy thế nào về việc sử dụng các toán tử bitwise để kiểm tra quyền và cách tiếp cận này để lưu trữ chúng?
Chia sẻ bài viết này
Bruno Skvorc
Bruno là nhà phát triển blockchain và nhà giáo dục kỹ thuật tại Web3 Foundation, nền tảng đang xây dựng thế hệ tiếp theo của Internet dành cho những người tự do. Anh ấy điều hành hai bản tin mà bạn nên đăng ký nếu quan tâm đến Web3. 0. Dot Leap đề cập đến sự phát triển hệ sinh thái và công nghệ của Web3, còn Đánh giá NFT đề cập đến sự phát triển của hệ sinh thái mã thông báo không thể thay thế [sưu tầm kỹ thuật số] bên trong trang web mới nổi này. Dự án đam mê hiện tại của anh ấy là RMRK. app, hệ thống NFT tiên tiến nhất trên thế giới, cho phép NFT sở hữu các NFT khác, NFT phản ứng với cảm xúc, NFT được quản lý một cách dân chủ và NFT có nhiều thứ cùng một lúc