Tôi đồng tình với tất cả các điểm trong câu trả lời xuất sắc của Bill Karwin.
Hỏi: Có bình thường không khi tạo một dạng xem cho truy vấn liên hợp đã thảo luận và sử dụng nó trong các phép nối, các lựa chọn con, v.v. của tôi?
Đ: Với MySQL, các phương pháp bình thường hơn là tránh sử dụng câu lệnh "CREATE VIEW".
Hỏi: Về mặt hiệu suất - nó sẽ kém hơn, bằng hay tốt hơn so với việc chỉ chèn nó vào các phép nối, mục chọn con, v.v.?
Đ: Tham chiếu đối tượng dạng xem sẽ có hiệu suất giống hệt dạng xem nội tuyến tương đương.
(Có thể phải thực hiện thêm một chút công việc dành cho thanh thiếu niên để tra cứu đối tượng dạng xem, kiểm tra các đặc quyền và sau đó thay thế tham chiếu dạng xem bằng SQL được lưu trữ, so với việc gửi một câu lệnh dài hơn một chút. Nhưng bất kỳ điều nào trong số đó sự khác biệt là không đáng kể.)
Hỏi: Có bất kỳ hạn chế nào của việc xem trong trường hợp này không?
Đ: Hạn chế lớn nhất là ở cách MySQL xử lý một dạng xem, cho dù nó được lưu trữ hay nội tuyến. MySQL sẽ luôn chạy truy vấn dạng xem và hiện thực hóa kết quả từ truy vấn đó dưới dạng bảng MyISAM tạm thời. Nhưng không có sự khác biệt ở đó cho dù định nghĩa dạng xem được lưu trữ hay nó được đưa vào nội tuyến. (Các chế độ xem quy trình RDBMS khác khác nhiều so với MySQL).
Một nhược điểm lớn của chế độ xem là các vị từ từ truy vấn bên ngoài KHÔNG BAO GIỜ bị đẩy xuống truy vấn chế độ xem. Mỗi khi bạn tham chiếu chế độ xem đó, ngay cả với một truy vấn cho một giá trị id duy nhất, MySQL sẽ chạy truy vấn chế độ xem và tạo một bảng MyISAM tạm thời (không có chỉ mục trên đó) và THÌ MySQL sẽ chạy truy vấn bên ngoài đối với tạm thời đó Bảng MyISAM.
Vì vậy, về mặt hiệu suất, hãy nghĩ đến một tham chiếu đến một chế độ xem ngang bằng với "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM
"và" INSERT INTO t (cols) SELECT ...
".
MySQL thực sự đề cập đến một dạng xem nội tuyến như một "bảng dẫn xuất" và tên đó có ý nghĩa rất nhiều, khi chúng ta hiểu MySQL đang làm gì với nó.
Sở thích cá nhân của tôi là không sử dụng câu lệnh "TẠO CHẾ ĐỘ XEM". Hạn chế lớn nhất (theo tôi thấy) là nó "ẩn" SQL đang được thực thi. Đối với trình đọc tương lai, tham chiếu đến chế độ xem trông giống như một bảng. Và sau đó, khi anh ta viết một câu lệnh SQL, anh ta sẽ tham chiếu chế độ xem giống như một bảng, rất thuận tiện. Sau đó, anh ấy quyết định sẽ tham gia vào bàn đó với chính nó, với một tham chiếu khác về nó. (Đối với tham chiếu thứ hai, MySQL cũng chạy lại truy vấn đó và tạo thêm một bảng MyISAM tạm thời (và không được lập chỉ mục) khác. Và bây giờ có một hoạt động JOIN trên đó. Và sau đó một vị từ "WHERE view.column ='foo'" được thêm vào trên truy vấn bên ngoài.
Nó kết thúc "ẩn" cải tiến hiệu suất rõ ràng nhất, trượt vị từ đó vào truy vấn chế độ xem.
Và sau đó, một người nào đó đến và quyết định họ sẽ tạo chế độ xem mới, tham chiếu đến chế độ xem cũ. Anh ấy chỉ cần một tập hợp con của các hàng và không thể sửa đổi chế độ xem hiện có vì điều đó có thể phá vỡ một cái gì đó, vì vậy anh ấy tạo một chế độ xem mới ... TẠO CHẾ ĐỘ XEM myview TỪ publicview p WHERE p.col ='foo'.
Và bây giờ, một tham chiếu đến myview sẽ chạy truy vấn publicview trước tiên, tạo một bảng MyISAM tạm thời, sau đó truy vấn myview sẽ chạy ngược lại điều đó, tạo một bảng MyISAM tạm thời khác, mà truy vấn bên ngoài sẽ chạy ngược lại.
Về cơ bản, sự tiện lợi của chế độ xem có khả năng gây ra các vấn đề về hiệu suất không chủ ý. Với định nghĩa dạng xem có sẵn trên cơ sở dữ liệu cho mọi người sử dụng, ai đó sẽ sử dụng nó, ngay cả khi nó không phải là giải pháp thích hợp nhất.
Ít nhất với chế độ xem nội tuyến, người viết câu lệnh SQL biết rõ hơn về SQL thực đang được thực thi và việc có tất cả những gì SQL được trình bày sẽ tạo cơ hội để điều chỉnh nó cho hiệu suất.
Hai xu của tôi.
TAMING BEASTLY SQL
Tôi nhận thấy rằng việc áp dụng các quy tắc định dạng thông thường (mà các công cụ của tôi tự động thực hiện) có thể biến SQL quái dị thành thứ mà tôi có thể đọc và làm việc.
SELECT row.col1
, row.col2
, person.*
FROM some_table row
LEFT
JOIN ( SELECT 'person' AS `person_type`
, p.id AS `id`
, CONCAT(p.first_name,' ',p.surname) AS `name`
FROM person p
UNION ALL
SELECT 'company' AS `person_type`
, c.id AS `id`
, c.name AS `name`
FROM company c
) person
ON person.id = row.person_id
AND person.person_type = row.person_type
Tôi cũng có khả năng tránh chế độ xem nội tuyến và sử dụng các biểu thức điều kiện trong danh sách CHỌN, mặc dù điều này sẽ khó sử dụng hơn đối với nhiều cột.
SELECT row.col1
, row.col2
, row.person_type AS ref_person_type
, row.person_id AS ref_person_id
, CASE
WHEN row.person_type = 'person' THEN p.id
WHEN row.person_type = 'company' THEN c.id
END AS `person_id`
, CASE
WHEN row.person_type = 'person' THEN CONCAT(p.first_name,' ',p.surname)
WHEN row.person_type = 'company' THEN c.name
END AS `name`
FROM some_table row
LEFT
JOIN person p
ON row.person_type = 'person'
AND p.id = row.person_id
LEFT
JOIN company c
ON row.person_type = 'company'
AND c.id = row.person_id