Khi bạn có một truy vấn hoặc thủ tục lưu trữ cần điều chỉnh hiệu suất, một số điều đầu tiên bạn thử là gì?
Khi bạn có một truy vấn hoặc thủ tục lưu trữ cần điều chỉnh hiệu suất, một số điều đầu tiên bạn thử là gì?
Câu trả lời:
Dưới đây là danh sách những thứ tiện dụng mà tôi luôn đưa cho ai đó hỏi tôi về tối ưu hóa.
Chúng tôi chủ yếu sử dụng Sybase, nhưng hầu hết các lời khuyên sẽ được áp dụng trên bảng.
Ví dụ, SQL Server đi kèm với một loạt các bit giám sát / điều chỉnh hiệu suất, nhưng nếu bạn không có bất cứ thứ gì như vậy (và thậm chí nếu bạn làm như vậy) thì tôi sẽ xem xét ...
99% các vấn đề tôi đã thấy là do đặt quá nhiều bảng vào một liên kết . Cách khắc phục cho việc này là thực hiện một nửa phép nối (với một số bảng) và lưu kết quả vào một bảng tạm thời. Sau đó thực hiện phần còn lại của truy vấn tham gia trên bảng tạm thời đó.
#temp
các bảng có thể thực hiện tốt hơn nhiều so với @table
các biến có khối lượng lớn (hàng nghìn hàng).Hơi lạc đề nhưng nếu bạn có quyền kiểm soát những vấn đề này ...
Mức độ cao và Tác động cao.
CREATE INDEX
Đảm bảo có các chỉ mục có sẵn cho bạn WHERE
và JOIN
các mệnh đề. Điều này sẽ tăng tốc độ truy cập dữ liệu rất nhiều.
Nếu môi trường của bạn là một trung tâm dữ liệu hoặc kho, các chỉ mục sẽ có rất nhiều cho hầu hết mọi truy vấn có thể hiểu được.
Trong môi trường giao dịch , số lượng chỉ mục nên thấp hơn và định nghĩa của chúng mang tính chiến lược hơn để bảo trì chỉ mục không làm giảm tài nguyên. (Bảo trì chỉ mục là khi các lá của chỉ mục phải được thay đổi để phản ánh sự thay đổi trong bảng bên dưới, như với INSERT, UPDATE,
và DELETE
hoạt động.)
Ngoài ra, hãy chú ý đến thứ tự của các trường trong chỉ mục - trường càng chọn lọc (cardinality càng cao), thì càng sớm trong chỉ mục sẽ xuất hiện. Ví dụ: giả sử bạn đang truy vấn ô tô đã sử dụng:
SELECT i.make, i.model, i.price
FROM dbo.inventory i
WHERE i.color = 'red'
AND i.price BETWEEN 15000 AND 18000
Giá thường có cardinality cao hơn. Có thể chỉ có vài chục màu có sẵn, nhưng có thể có hàng ngàn mức giá khác nhau.
Trong số các lựa chọn chỉ mục này, idx01
cung cấp đường dẫn nhanh hơn để đáp ứng truy vấn:
CREATE INDEX idx01 ON dbo.inventory (price, color)
CREATE INDEX idx02 ON dbo.inventory (color, price)
Điều này là do ít xe hơn sẽ thỏa mãn điểm giá hơn so với lựa chọn màu sắc, giúp công cụ truy vấn ít dữ liệu hơn để phân tích.
Tôi được biết là có hai chỉ mục rất giống nhau chỉ khác nhau theo thứ tự trường để tăng tốc độ truy vấn (tên, họ) trong một và (họ, tên) trong cái kia.
Một mẹo tôi mới học được là SQL Server có thể cập nhật các biến cục bộ cũng như các trường, trong một câu lệnh cập nhật.
UPDATE table
SET @variable = column = @variable + otherColumn
Hoặc phiên bản dễ đọc hơn:
UPDATE table
SET
@variable = @variable + otherColumn,
column = @variable
Tôi đã sử dụng điều này để thay thế các con trỏ / phép nối phức tạp khi thực hiện các phép tính đệ quy và cũng đạt được rất nhiều hiệu suất.
Dưới đây là chi tiết và mã ví dụ đã tạo ra những cải tiến tuyệt vời về hiệu suất: http://geekswithbloss.net/Rhames/archive/2008/10/28/calculating-ricky-totals-in-sql-server-2005---the-optimal. aspx
Giả sử MySQL ở đây, sử dụng GIẢI THÍCH để tìm hiểu những gì đang xảy ra với truy vấn, đảm bảo rằng các chỉ mục đang được sử dụng hiệu quả nhất có thể và cố gắng loại bỏ các loại tệp. MySQL hiệu suất cao: Tối ưu hóa, sao lưu, sao chép và nhiều hơn nữa là một cuốn sách tuyệt vời về chủ đề này cũng như Blog hiệu suất MySQL .
@Terrapin có một vài điểm khác biệt giữa isnull và coalesce đáng được đề cập (bên cạnh việc tuân thủ ANSI, đây là một điểm lớn đối với tôi).
Đôi khi trong SQL Server nếu bạn sử dụng OR trong mệnh đề where, nó sẽ thực sự kết hợp với hiệu suất. Thay vì sử dụng HOẶC chỉ cần thực hiện hai lựa chọn và liên kết chúng lại với nhau. Bạn nhận được kết quả tương tự với tốc độ 1000 lần.
Nói chung, tôi sẽ bắt đầu với các liên kết - Tôi sẽ loại từng đối tượng ra khỏi truy vấn một lần và chạy lại truy vấn để có ý tưởng nếu có một tham gia cụ thể nào đó tôi gặp vấn đề.
Trên tất cả các bảng tạm thời của tôi, tôi muốn thêm các ràng buộc duy nhất (khi thích hợp) để tạo các chỉ mục và các khóa chính (hầu như luôn luôn).
declare @temp table(
RowID int not null identity(1,1) primary key,
SomeUniqueColumn varchar(25) not null,
SomeNotUniqueColumn varchar(50) null,
unique(SomeUniqueColumn)
)
Tôi đã tạo thói quen luôn sử dụng các biến ràng buộc. Các biến liên kết có thể không giúp được nếu RDBMS không lưu các câu lệnh SQL. Nhưng nếu bạn không sử dụng các biến liên kết, RDBMS không có cơ hội sử dụng lại các kế hoạch thực hiện truy vấn và các câu lệnh SQL được phân tích cú pháp. Khoản tiết kiệm có thể rất lớn: http://www.akadia.com/service/ora_bind_variables.html . Tôi làm việc chủ yếu với Oracle, nhưng Microsoft SQL Server hoạt động khá giống nhau.
Theo kinh nghiệm của tôi, nếu bạn không biết liệu bạn có đang sử dụng biến liên kết hay không, thì có lẽ bạn không biết. Nếu ngôn ngữ ứng dụng của bạn không hỗ trợ chúng, hãy tìm ngôn ngữ đó. Đôi khi bạn có thể sửa truy vấn A bằng cách sử dụng các biến liên kết cho truy vấn B.
Sau đó, tôi nói chuyện với DBA của chúng tôi để tìm hiểu điều gì khiến RDBMS đau đớn nhất. Lưu ý rằng bạn không nên hỏi "Tại sao truy vấn này chậm?" Điều đó giống như yêu cầu bác sĩ của bạn lấy ra phụ lục của bạn. Chắc chắn truy vấn của bạn có thể là vấn đề, nhưng cũng có khả năng là có điều gì đó khác đang xảy ra. Là nhà phát triển, chúng tôi có xu hướng suy nghĩ về các dòng mã. Nếu một dòng chậm, sửa dòng đó. Nhưng RDBMS là một hệ thống thực sự phức tạp và truy vấn chậm của bạn có thể là triệu chứng của một vấn đề lớn hơn nhiều.
Cách quá nhiều mẹo điều chỉnh SQL là thần tượng sùng bái hàng hóa. Hầu hết thời gian vấn đề không liên quan hoặc liên quan tối thiểu đến cú pháp bạn sử dụng, do đó, tốt nhất là sử dụng cú pháp sạch nhất bạn có thể. Sau đó, bạn có thể bắt đầu xem xét các cách để điều chỉnh cơ sở dữ liệu (không phải truy vấn). Chỉ chỉnh cú pháp khi thất bại.
Giống như bất kỳ điều chỉnh hiệu suất, luôn luôn thu thập số liệu thống kê có ý nghĩa. Không sử dụng thời gian wallclock trừ khi đó là trải nghiệm người dùng bạn đang điều chỉnh. Thay vào đó, hãy nhìn vào những thứ như thời gian của CPU, các hàng được tìm nạp và các khối đọc ra khỏi đĩa. Quá thường xuyên mọi người tối ưu hóa cho những điều sai trái.
Chạy truy vấn bằng cách sử dụng VỚI (NoLock) là hoạt động tiêu chuẩn khá nhiều ở vị trí của tôi. Bất cứ ai cũng bắt gặp các truy vấn đang chạy trên các bảng hàng chục gigabyte mà không được lấy ra và bắn.
Chuyển đổi các truy vấn KHÔNG IN thành TRÁI PHIẾU TRÊN NỀN TẢNG nếu có thể. Ví dụ: nếu bạn muốn tìm tất cả các hàng trong Bảng 1 không được sử dụng bởi khóa ngoại trong Bảng 2, bạn có thể thực hiện việc này:
SELECT *
FROM Table1
WHERE Table1.ID NOT IN (
SELECT Table1ID
FROM Table2)
Nhưng bạn có được hiệu suất tốt hơn với điều này:
SELECT Table1.*
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.Table1ID
WHERE Table2.ID is null
@ DavidM
Giả sử MySQL ở đây, sử dụng GIẢI THÍCH để tìm hiểu điều gì đang xảy ra với truy vấn, đảm bảo rằng các chỉ mục đang được sử dụng hiệu quả nhất có thể ...
Trong SQL Server, kế hoạch thực hiện giúp bạn có được điều tương tự - nó cho bạn biết các chỉ mục nào đang bị tấn công, v.v.
Không nhất thiết là một thủ thuật hiệu năng SQL mỗi se nhưng chắc chắn có liên quan:
Một ý tưởng tốt sẽ là sử dụng memcached nếu có thể vì nó sẽ nhanh hơn nhiều khi chỉ lấy dữ liệu được biên dịch trực tiếp từ bộ nhớ thay vì lấy từ cơ sở dữ liệu. Ngoài ra còn có một hương vị của MySQL được tích hợp sẵn (bên thứ ba).
Hãy chắc chắn rằng độ dài chỉ mục của bạn càng nhỏ càng tốt. Điều này cho phép DB đọc nhiều khóa cùng một lúc từ hệ thống tệp, do đó tăng tốc độ tham gia của bạn. Tôi giả sử điều này hoạt động với tất cả các DB, nhưng tôi biết đó là một khuyến nghị cụ thể cho MySQL.
Tôi tìm kiếm:
SET NOCOUNT ON
Thường là dòng đầu tiên bên trong các thủ tục được lưu trữ của tôi, trừ khi tôi thực sự cần sử dụng @@ROWCOUNT
.
Trong SQL Server, sử dụng lệnh nolock. Nó cho phép lệnh select hoàn thành mà không phải chờ đợi - thường là các giao dịch khác kết thúc.
SELECT * FROM Orders (nolock) where UserName = 'momma'
Xóa các lệnh gọi hàm trong Sprocs trong đó rất nhiều hàng sẽ gọi hàm.
Đồng nghiệp của tôi đã sử dụng các cuộc gọi chức năng (lấy ví dụ cuối cùng từ userid làm ví dụ) để trả về các bản ghi rất rộng.
Được giao nhiệm vụ tối ưu hóa, tôi đã thay thế các lệnh gọi hàm trong sproc bằng mã của hàm: Tôi nhận được nhiều thời gian chạy của sprocs từ> 20 giây xuống <1.
Tôi thích sử dụng
isnull(SomeColThatMayBeNull, '')
Kết thúc
coalesce(SomeColThatMayBeNull, '')
Khi tôi không cần hỗ trợ nhiều đối số mà sự kết hợp mang lại cho bạn.
http://blog.falafel.com/2006/04/05/QueryServerArcanaISNULLVsCOALESCE.aspx
Không đặt tiền tố Tên thủ tục được lưu với "sp_" vì tất cả các thủ tục hệ thống bắt đầu bằng "sp_" và SQL Server sẽ phải tìm kiếm nhiều hơn để tìm thủ tục của bạn khi được gọi.
Đọc bẩn -
set transaction isolation level read uncommitted
Ngăn chặn các khóa chết trong đó tính toàn vẹn giao dịch không thực sự cần thiết (thường là đúng)