SQL Server 2014 Đột ngột chậm / Không chèn / Không liên quan đến phần cứng hoặc chỉ mục


8

Tôi đang chạy một 350GBcơ sở dữ liệu trên PC với ~ 40 triệu hàng.

SQL Server 2014, Win7, AMD 8350 @ 4.8GHZ, RAM 16 GB và SSD 500 GB (cơ sở dữ liệu được lưu trữ trên ổ SSD 500 GB của chính nó, với lưu lượng đọc / ghi 500MB / 500MB).

Cơ sở dữ liệu không được cập nhật, tôi chỉ phân tích / đọc nó. Với việc tạo ra một vài indexes, bất kỳ join, count(*)v.v., chỉ mất chưa đến 1 phút, điều này phù hợp với mục đích của tôi. Tôi đã chạy một số truy vấn (sau khi chạy một truy vấn tham gia duy nhất, 40-50 lần, nó trở nên chậm) trên dữ liệu và bây giờ các cuộc gọi mất 1 phút, vẫn chạy 20 phút sau.

Tôi theo dõi cẩn thận các tài nguyên hệ thống và tôi có thể thấy SSDcú đá khi truy vấn bắt đầu, nó đọc trong 20-30 giây, sau đó nó sẽ đọc 121kB/secondtrong 20 phút tiếp theo. Đây không phải là một vấn đề CPU, hoặc vấn đề đĩa. Tôi bị giới hạn với số lượng RAM của mình, tuy nhiên các cuộc gọi chạy tốt khi tôi tải cơ sở dữ liệu lần đầu tiên, bây giờ, không có gì chạy, 25 phút sau.

Thực tế, tôi không thể truy vấn cơ sở dữ liệu nữa, bất kỳ cuộc gọi nào cũng mất quá nhiều thời gian thậm chí là một SELECTcâu lệnh cơ bản . Tôi đã thử xây dựng lại các chỉ mục và cập nhật số liệu thống kê, nhưng không có sự khác biệt.

Tôi không có nhiều kinh nghiệm về vấn đề này nên hoàn toàn có thể truy vấn SQL của tôi không chính xác, trong trường hợp đó tôi sẽ gặp lỗi hoặc để nó hoàn thành việc thực hiện với 0 kết quả, nhưng không xảy ra.

Những gì tôi đang cố gắng làm là đếm tất cả các trường hợp của 'TypeID', trong 5 giây trước một thời gian dựa trên bảng ACALLS.

SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR,   ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON 
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)

WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and 
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime

Sau khi chạy "Ai đang chạy", nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


Tôi nghi ngờ điều này có liên quan đến số liệu thống kê trên các bảng và các loại xử lý được thực hiện cho các phép nối. Bạn nên xem xét các kế hoạch thực hiện cho các truy vấn: các phép nối vòng lặp lồng nhau có thể là một dấu hiệu của các vấn đề.
Gordon Linoff

Bạn đã thử với RECOMPILE chưa?

3
Đăng một kế hoạch thực hiện thực tế của một truy vấn chậm đáng ngạc nhiên. Truy vấn càng đơn giản càng tốt.
usr

1
Bạn đã cập nhật số liệu thống kê trên tất cả các bảng? Bạn đã xây dựng lại tất cả các chỉ mục? Thông tin trên sp_whoisactive: link
TT.

2
Các thống kê chờ đó hiển thị rất nhiều IO nhưng chúng tôi không biết tỷ lệ truy vấn là IO và CPU là gì. Thực hiện các bài kiểm tra mà tôi đề nghị như đăng kết quả.
usr

Câu trả lời:


2

Bạn có một truy vấn không SARGable - ngay cả khi bạn có các chỉ mục tốt, bạn không sử dụng chúng với truy vấn đó.

Đầu tiên, một phản ứng giật đầu gối với pageiolatch_sh là đọc các trang từ đĩa vào bộ đệm; bạn không có đủ RAM cho dữ liệu mà nó đang cố lấy.

Thứ hai, bạn cần xem xét kế hoạch thực hiện và việc sử dụng các chỉ mục của nó - hoặc thiếu nó.

Thoát khỏi việc sử dụng các chức năng trong các liên kết và WHERE của bạn và chỉ nhận dữ liệu bạn thực sự cần để bắt đầu.

  • "GIỮA ACALLS.StartTime và DATEADD (ss, -5, ACALLS.StartTime)" - thoát khỏi DATEADD đó trong GIỮA.

    • Nếu đây là cơ sở dữ liệu chỉ đọc, báo cáo, sau đó tạo bảng báo cáo chỉ với dữ liệu bạn cần, sau đó đặt các chỉ mục tổng hợp trên đó theo yêu cầu. Sử dụng cái đó để lấy các khóa chính / các khóa duy nhất khác của các hàng ACALLS bạn cần, sau đó lấy phần còn lại của dữ liệu ACALLS sau.
  • WHERE DATEPART (giờ, MainView.TimeStamp) GIỮA 10 và 13 và CAST (MainView.TimeStamp là ngày) = '2015-12-09'

    • điều tương tự - thoát khỏi CAST - thay đổi '2015-12-09' thành một hoặc hai @parameter của loại dữ liệu phù hợp cho MainView.TimeStamp> = @StartTimestamp VÀ MainView.TimeStamp <@EndTimestamp

    • và loại bỏ DATEPART đó bằng cách hạn chế @StartTimestamp và @EndTimestamp để bao gồm cả tiêu chí giờ của bạn.

Có lẽ tải lên bảng #temp chỉ bằng các khóa chính / duy nhất của các hàng đáp ứng các tiêu chí MainView đó trước khi tham gia.

Hmm ... đồng thời, nếu Mainview là chế độ xem phức tạp, hãy đi thẳng đến các bảng cơ sở để tải lên bảng #temp đó

Đừng quên sử dụng Profiler để kiểm tra và xem nếu thêm các chỉ mục (gộp nếu cần) trên bảng #temp hoặc bảng phân tầng khác là lãi ròng hay lỗ ròng :).


1

tạo một chỉ mục không phân cụm tổng hợp trên mainview (typeid, dấu thời gian).

thay đổi "nơi" của bạn trên mainview để bạn không sử dụng chức năng đối với các cột của chế độ xem chính. điều này có thể yêu cầu bạn xác định trước các giá trị này dưới dạng các biến trước khi chạy truy vấn nếu bạn cần các giá trị này linh hoạt hơn.

WHERE MainView.TimeStamp BETWEEN '2015-12-09 10:00' and '2015-12-09 13:00'

tạo một chỉ mục không bao gồm trên ACALLS.StartTime.

thay đổi tham gia thành ACALLS để được

WHERE ACALLS.StartTime BETWEEN DATEADD(ss,-5,MainView.TimeStamp) AND MainView.TimeStamp

theo hiểu biết của tôi, điều đó sẽ xử lý logic của bạn và tham gia với hiệu suất khá cao và giúp bạn thoát khỏi IO.

Tôi đoán tốt nhất về những gì bạn đang chạy vào là dữ liệu của bạn đang bị xóa khỏi bộ đệm và / hoặc tempdb đang tràn vào đĩa mọi lúc, vì vậy giải pháp tốt nhất tôi thường tìm thấy là viết các truy vấn tốt hơn chỉ để viết hạn chế sử dụng tempdb và bộ nhớ và các vấn đề tiềm ẩn biến mất.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.