Chúng tôi có một trang web khách hàng với cơ sở dữ liệu SQL 2012 50Gb trên máy chủ có RAM trên 100 GB.Bắt buộc SQL Server nạp trước toàn bộ cơ sở dữ liệu vào bộ nhớ
Khi ứng dụng được sử dụng, máy chủ SQL thực hiện công việc tuyệt vời trong việc lưu bộ nhớ đệm vào bộ nhớ nhưng hiệu suất tăng từ bộ nhớ đệm xảy ra thời gian SECOND một truy vấn được chạy chứ không phải là truy vấn đầu tiên.
Để cố gắng tối đa hóa bộ nhớ cache lượt truy cập lần đầu tiên truy vấn được chạy, chúng tôi đã viết một proc đó lặp qua từng chỉ số của tất cả các bảng trong toàn bộ DB, chạy này:
SELECT * INTO #Cache
FROM ' + @tablename + ' WITH (INDEX (' + @indexname + '))'
Trong một nỗ lực để buộc một to, xấu, được đọc nhiều dữ liệu nhất có thể. Chúng tôi đã lên kế hoạch chạy 15 phút một lần và công việc tuyệt vời nói chung.
Nếu không tranh luận về các tắc nghẽn khác, thông số phần cứng, kế hoạch truy vấn hoặc tối ưu hóa truy vấn, có ai có ý tưởng nào tốt hơn về cách thực hiện tác vụ tương tự này không?
CẬP NHẬT
Cảm ơn bạn đã đề xuất. Đã xóa "INTO #Cache". Thử nghiệm & nó đã không làm cho một sự khác biệt trên điền vào bộ đệm.
Đã thêm: Thay vì Chọn *, tôi chỉ chọn CHỈ các phím từ Chỉ mục. Điều này (rõ ràng) là nhiều hơn-to-điểm và nhanh hơn nhiều.
Đã thêm: Đọc & Chỉ mục ngăn chặn bộ nhớ cache.
Dưới đây là các mã hiện tại: (hy vọng nó hữu ích cho người khác)
CREATE VIEW _IndexView
as
-- Easy way to access sysobject and sysindex data
SELECT
so.name as tablename,
si.name as indexname,
CASE si.indid WHEN 1 THEN 1 ELSE 0 END as isClustered,
CASE WHEN (si.status & 2)<>0 then 1 else 0 end as isUnique,
dbo._GetIndexKeys(so.name, si.indid) as Keys,
CONVERT(bit,CASE WHEN EXISTS (SELECT * FROM sysconstraints sc WHERE object_name(sc.constid) = si.name) THEN 1 ELSE 0 END) as IsConstraintIndex
FROM sysobjects so
INNER JOIN sysindexes si ON so.id = si.id
WHERE (so.xtype = 'U')--User Table
AND ((si.status & 64) = 0) --Not statistics index
AND ( (si.indid = 0) AND (so.name <> si.name) --not a default clustered index
OR
(si.indid > 0)
)
AND si.indid <> 255 --is not a system index placeholder
UNION
SELECT
so.name as tablename,
si.name as indexname,
CASE si.indid WHEN 1 THEN 1 ELSE 0 END as isClustered,
CASE WHEN (si.status & 2)<>0 then 1 else 0 end as isUnique,
dbo._GetIndexKeys(so.name, si.indid) as Keys,
CONVERT(bit,0) as IsConstraintIndex
FROM sysobjects so
INNER JOIN sysindexes si ON so.id = si.id
WHERE (so.xtype = 'V')--View
AND ((si.status & 64) = 0) --Not statistics index
GO
CREATE PROCEDURE _CacheTableToSQLMemory
@tablename varchar(100)
AS
BEGIN
DECLARE @indexname varchar(100)
DECLARE @xtype varchar(10)
DECLARE @SQL varchar(MAX)
DECLARE @keys varchar(1000)
DECLARE @cur CURSOR
SET @cur = CURSOR FOR
SELECT v.IndexName, so.xtype, v.keys
FROM _IndexView v
INNER JOIN sysobjects so ON so.name = v.tablename
WHERE tablename = @tablename
PRINT 'Caching Table ' + @Tablename
OPEN @cur
FETCH NEXT FROM @cur INTO @indexname, @xtype, @keys
WHILE (@@FETCH_STATUS = 0)
BEGIN
PRINT ' Index ' + @indexname
--BEGIN TRAN
IF @xtype = 'V'
SET @SQL = 'SELECT ' + @keys + ' FROM ' + @tablename + ' WITH (noexpand, INDEX (' + @indexname + '))' --
ELSE
SET @SQL = 'SELECT ' + @keys + ' FROM ' + @tablename + ' WITH (INDEX (' + @indexname + '))' --
EXEC(@SQL)
--ROLLBACK TRAN
FETCH NEXT FROM @cur INTO @indexname, @xtype, @keys
END
CLOSE @cur
DEALLOCATE @cur
END
GO
Cứ 15 phút một lần? Nếu cơ sở dữ liệu của bạn là 50 GB và bạn đã cho SQL Server 100 GB bộ nhớ, thì bạn chỉ phải thực hiện việc này một lần, khi khởi động. –
Tại sao bạn chèn vào bảng tạm thời? –
@MartinSmith Tôi nghi ngờ dev, người đã viết nó thấy rằng nhanh hơn để chọn tất cả dữ liệu đó vào bảng #temp hơn là hiển thị kết quả vào một loạt các lưới trong SSMS (có thể qua kết nối mạng rất chậm). –