में पूरे डेटाबेस को प्री-कैश करने के लिए मजबूर करना हमारे पास 100+ जीबी रैम वाले सर्वर पर 50 जीबी SQL 2012 डेटाबेस वाला क्लाइंट साइट है।SQL सर्वर को मेमोरी
जैसा कि एप्लिकेशन का उपयोग किया जाता है, SQL सर्वर स्मृति में डीबी को कैशिंग करने का एक अच्छा काम करता है लेकिन कैशिंग से प्रदर्शन वृद्धि दूसरी बार क्वेरी होती है, पहले नहीं।
अधिकतम करने के लिए कैश पहली बार प्रश्नों चलाए जा रहे हैं हिट की कोशिश करने के लिए, हम एक proc कि पूरे डीबी के भीतर हर तालिका के हर सूचकांक के माध्यम से दोहराता, यह चल रहा है ने लिखा है:
SELECT * INTO #Cache
FROM ' + @tablename + ' WITH (INDEX (' + @indexname + '))'
एक मजबूर करने की कोशिश में जितना संभव हो उतना डेटा के लिए बड़े, बदसूरत, समेकित पढ़ा। हमने इसे हर 15 मिनट में चलाने के लिए निर्धारित किया है, और यह सामान्य रूप से एक महान काम करता है।
अन्य बाधाओं, हार्डवेयर चश्मा, क्वेरी प्लान, या क्वेरी ऑप्टिमाइज़ेशन पर बहस किए बिना, क्या किसी के पास इस कार्य को पूरा करने के बारे में कोई बेहतर विचार है?
अद्यतन
सुझावों के लिए धन्यवाद। "INTO # कैश" हटा दिया गया। परीक्षण & ने बफर भरने पर कोई फर्क नहीं पड़ता।
जोड़ा गया: चयन करने के बजाय *, मैं केवल इंडेक्स से चाबियाँ चुन रहा हूं। यह (जाहिर है) अधिक से अधिक बिंदु है और बहुत तेज़ है।
जोड़ा गया: & कैश प्रतिबंध सूचकांक भी पढ़ें। (आशा है कि यह किसी और के लिए उपयोगी है) सब से
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
हर 15 मिनट? यदि आपका डेटाबेस 50 जीबी है और आपने SQL सर्वर 100+ जीबी मेमोरी दी है, तो आपको स्टार्टअप पर केवल एक बार ऐसा करना होगा। –
आप एक temp तालिका में क्यों डालने जा रहे हैं? –
@ मार्टिनस्मिथ मुझे संदेह है कि जिस देव ने इसे लिखा है, वह पाया गया है कि एसएसएमएस में संभवतः आउटपुट को एक बहुत ही धीमी नेटवर्क कनेक्शन पर आउटपुट प्रस्तुत करने के बजाय #temp तालिका में उस डेटा को चुनना तेज़ था। अधिकांश पैरामीटर के लिए –