2010-03-10 29 views
6

Giả sử tôi có một bảng rất dài (~ 35 triệu hàng) được gọi là TimeCard chỉ với 5 cột (tableID, CompanyID, UserID, ProjectID, DailyHoursWorked, entryDate). Đây là một bảng chuyển tiếp khá đơn giản ghi lại giờ làm việc của nhân viên mỗi ngày cho mỗi dự án cho mỗi công ty.Giảm tốc độ tại Chế độ xem chỉ mục cho SQL 2005

Tôi hiện cần tạo báo cáo để tìm hiểu tổng số giờ làm việc của mỗi nhân viên mỗi tháng cho mỗi dự án cho bất kỳ công ty cụ thể nào. Thay vì thực hiện tổng hợp khi báo cáo chạy, tôi muốn xây dựng một cấu trúc dữ liệu giống như bảng đã có tất cả dữ liệu Công ty/Dự án/Người dùng được tổng hợp theo tháng, vì vậy khi báo cáo chạy, tôi chỉ có thể truy vấn cấu trúc dữ liệu đó trực tiếp mà không thực hiện bất kỳ tập hợp thời gian chạy nào kể từ ~ 35 triệu bản ghi có thể mất vài phút.

Vì vậy, tôi có 2 cách khác nhau. Một tạo ra một bảng vật lý thêm với (CompanyID, UserID, ProjectID, MonthlyHoursWorked, Month) làm cột của tôi và chỉ sử dụng kích hoạt tại bảng TimeCard để sửa đổi các giá trị tại bảng phụ. Hoặc tôi có thể tạo Chế độ xem được lập chỉ mục. Vì vậy, tôi đã thử cả hai. Trước tiên, tôi đã thử chế độ xem được lập chỉ mục với mã sau:

CREATE VIEW [dbo].[vw_myView] WITH SCHEMABINDING AS 
SELECT 
JobID, 
ProjectID, 
Sum(DailyHoursWorked) AS MonthTotal, 
DATEADD(Month, DATEDIFF(Month, 0, entryDate), 0) AS entryMonth, 
CompanyID, 
COUNT_BIG(*) AS Counter 
FROM 
dbo.TimeCard 
Group By DATEADD(Month, DATEDIFF(Month, 0, entryDate), 0), JobID, ProjectID, CompanyID 

Go 
CREATE UNIQUE CLUSTERED INDEX [IX_someIndex] ON [dbo].[vw_myView] 
(
[CompanyID] ASC, 
[entryMonth] ASC, 
[UserID] ASC, 
[ProjectID] ASC 
) 

Chế độ xem được lập chỉ mục được tạo chính xác và tổng cộng ~ 5 triệu hàng tổng.

Tuy nhiên, mỗi lần nếu tôi xóa bộ nhớ cache SQL và chạy truy vấn sau: * chọn * từ vw_myView nơi companyID = 1 *, mất gần 3 phút. Nếu tôi đi với các tuyến đường thêm bảng như tôi đã đề cập ở trên, với bộ nhớ cache của tôi xóa, phải mất khoảng 4 giây.

Câu hỏi của tôi là, được lập chỉ mục Xem lựa chọn không phù hợp cho trường hợp cụ thể này? Đặc biệt tôi quan tâm để biết nếu toàn bộ xem được lập chỉ mục được tính lại/tổng hợp lại mỗi khi bảng bên dưới (TimeCard) được thay đổi hoặc khi truy vấn chạy với nó?

Cảm ơn!

+0

Bạn đang sử dụng phiên bản SQL Server 2005 nào? – RedFilter

+0

Thay vì có ngày đầy đủ của tháng đầu tiên trong 'entryMonth', bạn không thể có' MONTH (entryDate) 'và có thể' YEAR (entryDate) 'là INTs? Có vẻ dễ dàng hơn nhiều với tôi (nhưng sau đó lại - tôi không biết yêu cầu chính xác của bạn) .... –

Trả lời

0

Tôi sẽ không sử dụng chế độ xem cho việc này. Tôi nghĩ rằng bảng dân cư do kích hoạt là con đường để đi. Nhưng đừng quên điều chỉnh tổng số để cập nhật và xóa cũng như chèn.

+1

Trình kích hoạt không phải là rất nhanh. –

+0

Chế độ xem thường chậm hơn so với trình kích hoạt (đặc biệt nếu bạn chồng chúng lên trên nhau) và trình kích hoạt có thể được viết chính xác để nhanh. – HLGEM

2

Nếu bạn không sử dụng một trong hai Enterprise hoặc Developer phiên bản, sau đó bạn cần phải sử dụng with (noexpand) gợi ý:

select * 
from vw_myView with (noexpand) 
where companyID = 1 

Khi thay đổi dữ liệu cơ bản, quan điểm chỉ sẽ cập nhật hàng liên quan đến dữ liệu đã thay đổi, không phải toàn bộ bảng. Điều này có thể có tác động bất lợi trên cơ sở dữ liệu OLTP với mức độ chèn cao, nhưng nếu việc sử dụng chỉ vừa phải, không nên đặt ra vấn đề về hiệu suất.

Một tip from Microsoft:

Là một khuyến nghị chung, bất kỳ sửa đổi hoặc cập nhật nào quan điểm hoặc các bảng cơ sở là cơ sở để xem nên được thực hiện theo lô nếu có thể, chứ không phải là singleton hoạt động. Điều này có thể làm giảm một số chi phí trong chế độ xem bảo trì.

+0

Những gì tôi không nhận được là tại sao phải mất 3 phút cho một truy vấn đơn giản nếu tôi xóa bộ nhớ cache và không có giá trị bảng cơ sở nào thay đổi. Liệu nó thực sự làm toàn bộ tập hợp một lần nữa? – TheYouth

+0

@TheYouth: bạn đã thử gợi ý 'with (noexpand)' chưa? – RedFilter

+1

+1 nếu bạn quên thêm WITH (NOEXPAND) trên các phiên bản EXPRESS hoặc DEVELOPER của SQL Server, trình tối ưu hóa sẽ không sử dụng chế độ xem được lập chỉ mục nhưng chọn từ các bảng bên dưới. –

0

Tôi không nghĩ, bạn cần chế độ xem được lập chỉ mục (tôi không nói, chế độ xem được lập chỉ mục là ý tưởng xấu/tốt). Tôi nghĩ, bạn cần chỉ mục trên cột "CompanyID" và "EntryDate".Sau đó, bạn nên sử dụng điều kiện "WHERE CompanyID = @CompanyID AND EntryDate> = @StartDate AND EntryDate < = @EndDate".

Nếu bảng được xử lý sơ bộ theo "EntryDate", bạn có thể sử dụng chỉ mục cụm trên cột "EntryDate".

Sau này, tôi nghĩ câu lệnh chọn sẽ nhanh hơn nhiều ngay bây giờ.

+1

chỉ mục nhóm trên chế độ xem đã sử dụng CompanyID làm cột đầu tiên của nó - điều đó thực sự cần thực hiện. Tôi không thấy bất kỳ lợi ích nào trong một chỉ mục trên (CompanyID, EntryDate) - dường như không có bất kỳ truy vấn nào bằng cách sử dụng EntryDate, vậy điểm lập chỉ mục nó là gì? –

+0

Thẻ thời gian được lập chỉ mục với entryDate, companyID, userID, projectID, tất cả trong các chỉ mục không được nhóm riêng biệt. Những gì tôi không nhận được là tại sao phải mất 3 phút cho một truy vấn đơn giản nếu tôi xóa bộ nhớ cache. Liệu nó thực sự làm toàn bộ tập hợp một lần nữa? – TheYouth

+0

Bạn đã shold lọc nó bằng EntryDate. Nếu bạn biết, bạn đã có một thông tin tổng hợp về Januar 2010, bạn không cần chọn ti từ bảng chính một lần nữa. Nếu bạn sử dụng chỉ mục cụm trên cột "EntryDate" (không có CompanyID) - bạn sẽ nhận được hiệu suất tốt hơn cho các lựa chọn dựa trên cột này. – TcKs

1

Tôi nghĩ bạn đang đi đúng hướng với Chế độ xem chỉ mục. Tuy nhiên, bạn có đặt chỉ mục trên bảng bạn đang truy vấn từ, TimeCard cho các cột tổng hợp của mình hay không. Bạn cần lập Chỉ mục là JobID, ProjectID, entryDate, CompanyID (1 chỉ mục). Nếu bạn sử dụng 1 chỉ mục cho mỗi cột, nó sẽ KHÔNG giải quyết các vấn đề của bạn vì Query sẽ phải sử dụng tất cả 4 chỉ mục cùng nhau.

Tôi nghĩ việc sử dụng trình kích hoạt sẽ chậm nhưng theo một cách khác. Nó sẽ làm cho truy vấn của bạn nhanh hơn nhưng nó sẽ làm chậm mọi chèn bạn làm vào TimeCard. Nếu bạn quyết định đi với Trình kích hoạt thì tôi sẽ đảm bảo rằng tôi lập chỉ mục bảng đó hoặc cũng có thể chậm, không chậm 3 phút, nhưng vẫn chậm để sắp xếp và trả về dữ liệu.

+2

Tôi không thấy các chỉ mục sẽ trợ giúp như thế nào, truy vấn sẽ chọn bằng 'CompanyID', đã được lập chỉ mục. – RedFilter

+0

Thẻ thời gian được lập chỉ mục với entryDate, companyID, userID, projectID, tất cả trong các chỉ mục không được nhóm riêng biệt. Những gì tôi không nhận được là tại sao phải mất 3 phút cho một truy vấn đơn giản nếu tôi xóa bộ nhớ cache. Liệu nó thực sự làm toàn bộ tập hợp một lần nữa? – TheYouth

+0

Tôi nghĩ là vậy. Tuy nhiên, tôi nghĩ sẽ tốt hơn nếu bạn có 1 chỉ mục không phải cụm cho entryDate, companyID, userID, projectID. Có 4 chỉ mục, một cho mỗi cột đó không thực sự giúp bạn vì Group By của bạn đang sử dụng tất cả 4 chỉ mục cùng nhau. Vì vậy, bạn muốn 1 chỉ mục có tất cả 4 cột trong đó. –

0

Bạn có xem xét phân vùng bảng không. Bạn có thể nghĩ về sự kết hợp của danh sách và bảng phân vùng băm.

0

Vâng, ý tưởng về chế độ xem được lập chỉ mục chắc chắn là tốt và nếu bạn có thể tạo chỉ mục nhóm trên đó - hoàn hảo. Nó phải nhanh - tốt hơn 3 phút cho một truy vấn!

Mặt khác: nếu những khối thông tin đó chỉ được cập nhật, ví dụ: mỗi tháng một lần hoặc một lần mỗi tuần (hoặc thậm chí mỗi đêm), có thể tốt hơn là chỉ đưa những người đó vào một bảng riêng biệt DailyTimeCard được điền/cập nhật bằng ví dụ: một gói SSIS thường xuyên.

Tôi không khuyên bạn nên sử dụng trình kích hoạt để cập nhật bảng thực tế như vậy - nếu bạn thực sự thực sự cần có dữ liệu cập nhật nhất vào mỗi giây nhất định trong ngày, sau đó giữ nguyên chế độ xem được lập chỉ mục.

Tuy nhiên, chế độ xem được lập chỉ mục của bạn thực hiện khá nhiều việc nâng hạng nặng - nó tính tổng cộng, nó nhóm theo và cứ tiếp tục như vậy. Luôn cập nhật thông tin đó, trong khi các thay đổi bảng TimeCard bên dưới của bạn và được cập nhật, sẽ gây ra một số tải trên hệ thống của bạn - khó có thể nói số lượng - nhưng có thể khá đáng chú ý.

Nếu bạn tìm cách trích xuất thông tin mình cần - nhóm và tổng hợp một lần và sau đó lưu trữ dữ liệu tổng hợp đó vào bảng thực tế riêng biệt - bạn nên có cả hai: truy vấn nhanh và nhanh trên bảng DailyTimeCard và phần còn lại của hệ thống của bạn sẽ ít gánh nặng hơn với việc giữ chế độ xem được lập chỉ mục luôn cập nhật.

Có thể đó không phải là giải pháp bạn đang tìm kiếm - nhưng chỉ cần suy nghĩ về nó một chút. Nó có thể - hoặc có thể không - làm việc cho bạn!

Các vấn đề liên quan