SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...
Việc sử dụng một cột bên trong một biểu thức hoặc hàm như thế này sẽ làm hỏng bất kỳ cơ hội nào của truy vấn bằng cách sử dụng chỉ mục để giúp tối ưu hóa truy vấn. Truy vấn hiển thị ở trên buộc phải thực hiện quét bảng.
Tuyên bố về "truy cập hiệu quả" là gây hiểu lầm. Có nghĩa là sau khi truy vấn kiểm tra một hàng với tài liệu JSON, nó có thể trích xuất một trường mà không cần phải phân tích cú pháp văn bản của cú pháp JSON. Nhưng nó vẫn cần quét bảng để tìm kiếm các hàng. Nói cách khác, truy vấn phải kiểm tra mọi hàng.
Tương tự, nếu tôi đang tìm kiếm những người có tên "Bill" trong danh bạ điện thoại, tôi vẫn phải đọc từng trang trong danh bạ, ngay cả khi những cái tên đầu tiên đã được đánh dấu để giúp phát hiện họ nhanh hơn một chút.
MySQL 5.7 cho phép bạn xác định một cột ảo trong bảng, sau đó tạo một chỉ mục trên cột ảo.
ALTER TABLE t1
ADD COLUMN series AS (JSON_EXTRACT(data, '$.series')),
ADD INDEX (series);
Sau đó, nếu bạn truy vấn cột ảo, nó có thể sử dụng chỉ mục và tránh quét bảng.
SELECT * FROM t1
WHERE series IN ...
Điều này thật hay, nhưng hơi thiếu sót khi sử dụng JSON. Phần hấp dẫn của việc sử dụng JSON là nó cho phép bạn thêm các thuộc tính mới mà không cần phải thực hiện ALTER TABLE. Nhưng hóa ra bạn phải xác định một cột bổ sung (ảo), nếu bạn muốn tìm kiếm các trường JSON với sự trợ giúp của chỉ mục.
Nhưng bạn không phải xác định các cột và chỉ mục ảo cho mọi trong tài liệu JSON — chỉ những người bạn muốn tìm kiếm hoặc sắp xếp. Có thể có các thuộc tính khác trong JSON mà bạn chỉ cần trích xuất trong danh sách chọn như sau:
SELECT JSON_EXTRACT(data, '$.series') AS series FROM t1
WHERE <other conditions>
Tôi thường nói rằng đây là cách tốt nhất để sử dụng JSON trong MySQL. Chỉ trong danh sách chọn.
Khi bạn tham chiếu đến các cột trong các mệnh đề khác (THAM GIA, WHERE, GROUP BY, HAVING, ORDER BY), sẽ hiệu quả hơn nếu sử dụng các cột thông thường, không phải các trường trong tài liệu JSON.
Tôi đã trình bày một bài nói chuyện có tên Cách sử dụng JSON trong MySQL Sai tại hội nghị Percona Live vào tháng 4 năm 2018. Tôi sẽ cập nhật và lặp lại bài nói chuyện tại Oracle Code One vào mùa thu.
Có các vấn đề khác với JSON. Ví dụ:trong các thử nghiệm của tôi, nó yêu cầu dung lượng lưu trữ cho tài liệu JSON gấp 2-3 lần so với các cột thông thường lưu trữ cùng một dữ liệu.
MySQL đang quảng bá mạnh mẽ các khả năng JSON mới của họ, phần lớn là để khuyên mọi người không nên di chuyển sang MongoDB. Nhưng lưu trữ dữ liệu hướng tài liệu như MongoDB về cơ bản là một cách tổ chức dữ liệu phi quan hệ. Nó khác với quan hệ. Tôi không nói cái này tốt hơn cái kia, nó chỉ là một kỹ thuật khác, phù hợp với các loại truy vấn khác nhau.
Bạn nên chọn sử dụng JSON khi JSON làm cho các truy vấn của bạn hiệu quả hơn.
Đừng chọn công nghệ chỉ vì nó mới hoặc vì mục đích thời trang.
Chỉnh sửa:Việc triển khai cột ảo trong MySQL được cho là sử dụng chỉ mục nếu mệnh đề WHERE của bạn sử dụng chính xác biểu thức giống như định nghĩa của cột ảo. Đó là, những điều sau nên sử dụng chỉ mục trên cột ảo, vì cột ảo được xác định AS (JSON_EXTRACT(data,"$.series"))
SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...
Ngoại trừ tôi đã phát hiện ra bằng cách thử nghiệm tính năng này rằng nó KHÔNG hoạt động vì một số lý do nếu biểu thức là một hàm trích xuất JSON. Nó hoạt động với các loại biểu thức khác, không chỉ các hàm JSON. CẬP NHẬT:điều này được báo cáo cuối cùng cũng hoạt động trong MySQL 5.7.33.