Tham khảo nhận xét của bạn:
@MarcB cơ sở dữ liệu được chuẩn hóa, chuỗi CSV đến từ giao diện người dùng. "Lấy cho tôi dữ liệu cho những người sau:101,202,303"
Câu trả lời này chỉ tập trung vào những con số được phân tách bằng dấu phẩy. Bởi vì, hóa ra, bạn thậm chí còn không nói về FIND_IN_SET
sau tất cả.
Có, bạn có thể đạt được những gì bạn muốn. Bạn tạo một câu lệnh đã chuẩn bị sẵn chấp nhận một chuỗi làm tham số như trong Câu trả lời gần đây
này của tôi. Trong câu trả lời đó, hãy xem khối thứ hai hiển thị QUY TRÌNH TẠO
và tham số thứ 2 của nó chấp nhận một chuỗi như (1,2,3)
. Tôi sẽ quay lại vấn đề này trong giây lát.
Không phải bạn cần xem nó @spraff mà những người khác có thể. Nhiệm vụ là lấy loại
! =ALL và could_keys
và các khóa
của Giải thích để không hiển thị null, như bạn đã hiển thị trong khối thứ hai của mình. Để có cách đọc chung về chủ đề này, hãy xem bài viết Hiểu biết Đầu ra của EXPLAIN
và Trang hướng dẫn sử dụng MySQL có tên GIẢI THÍCH Thông tin bổ sung
.
Bây giờ, quay lại (1,2,3)
tham khảo trên. Chúng tôi biết từ nhận xét của bạn và kết quả Giải thích thứ hai trong câu hỏi của bạn rằng nó đáp ứng các điều kiện mong muốn sau:
- type =range (và đặc biệt không phải TẤT CẢ). Xem tài liệu ở trên về điều này. khóa
- không rỗng
Đây chính xác là những điều kiện bạn có trong đầu ra Giải thích thứ hai và đầu ra có thể được nhìn thấy với truy vấn sau:
explain
select * from ratings where id in (2331425, 430364, 4557546, 2696638, 4510549, 362832, 2382514, 1424071, 4672814, 291859, 1540849, 2128670, 1320803, 218006, 1827619, 3784075, 4037520, 4135373, ... use your imagination ..., ..., 4369522, 3312835);
nơi tôi có 999 giá trị trong in
đó danh sách mệnh đề. Đó là mẫu từ câu trả lời này
của tôi trong Phụ lục D hơn là tạo một chuỗi csv ngẫu nhiên như vậy, được bao quanh bởi các dấu ngoặc đơn mở và đóng.
Và lưu ý đầu ra Giải thích sau cho phần tử 999 đó trong mệnh đề dưới đây:
Mục tiêu đạt được. Bạn đạt được điều này với một proc được lưu trữ tương tự như proc mà tôi đã đề cập trước đây trong liên kết này
sử dụng BÁO CÁO CHUẨN BỊ
(và những thứ đó sử dụng concat ()
theo sau là EXECUTE
).
Chỉ mục được sử dụng, một Tablescan (có nghĩa là xấu) không được trải nghiệm. Các bài đọc khác là Loại tham gia phạm vi
, bất kỳ tài liệu tham khảo nào bạn có thể tìm thấy trên MySQL's Cost-Based Optimizer (CBO), câu trả lời
này từ vladr mặc dù đã có ngày tháng, theo dõi BẢNG PHÂN TÍCH
, cụ thể là sau những thay đổi dữ liệu quan trọng. Lưu ý rằng ANALYZE có thể mất một lượng thời gian đáng kể để chạy trên các tập dữ liệu cực lớn. Đôi khi nhiều giờ.
Các cuộc tấn công Sql Injection:
Việc sử dụng các chuỗi được chuyển đến Thủ tục được lưu trữ là một vectơ tấn công cho các cuộc tấn công SQL Injection. Phải có các biện pháp phòng ngừa để ngăn chặn chúng khi sử dụng dữ liệu do người dùng cung cấp. Nếu quy trình của bạn được áp dụng dựa trên id của chính bạn do hệ thống của bạn tạo ra, thì bạn đã an toàn. Tuy nhiên, lưu ý rằng các cuộc tấn công SQL Injection cấp 2 xảy ra khi dữ liệu được đưa vào đúng vị trí của các quy trình không làm sạch dữ liệu đó trong bản chèn hoặc bản cập nhật trước đó. Các cuộc tấn công được thực hiện trước thông qua dữ liệu và được sử dụng sau (một loại bom hẹn giờ).
Vì vậy, câu trả lời này là Kết thúc phần lớn.
Dưới đây là chế độ xem của cùng một bảng với một sửa đổi nhỏ đối với nó để cho thấy Máy quét bảng đáng sợ sẽ trông giống như trong truy vấn trước (nhưng đối với một cột không được lập chỉ mục có tên là thing
).
Hãy xem định nghĩa bảng hiện tại của chúng tôi:
CREATE TABLE `ratings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5046214 DEFAULT CHARSET=utf8;
select min(id), max(id),count(*) as theCount from ratings;
+---------+---------+----------+
| min(id) | max(id) | theCount |
+---------+---------+----------+
| 1 | 5046213 | 4718592 |
+---------+---------+----------+
Lưu ý rằng cột điều
trước đây là một cột int nullable.
update ratings set thing=id where id<1000000;
update ratings set thing=id where id>=1000000 and id<2000000;
update ratings set thing=id where id>=2000000 and id<3000000;
update ratings set thing=id where id>=3000000 and id<4000000;
update ratings set thing=id where id>=4000000 and id<5100000;
select count(*) from ratings where thing!=id;
-- 0 rows
ALTER TABLE ratings MODIFY COLUMN thing int not null;
-- current table definition (after above ALTER):
CREATE TABLE `ratings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5046214 DEFAULT CHARSET=utf8;
Và sau đó là Giải thích đó là một Tablescan (đối với cột điều
):