এসকিউএল সার্ভার: দ্রুত অনুসন্ধান করা, তবে পদ্ধতি থেকে ধীর


257

একটি কোয়েরি দ্রুত চলে:

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

সাবট্রি ব্যয়: 0.502

কিন্তু একই এসকিউএলটিকে একটি সঞ্চিত পদ্ধতিতে রাখার কাজটি ধীর গতিতে চলেছে এবং একেবারে ভিন্ন বাস্তবায়নের পরিকল্পনার সাথে

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

EXECUTE ViewOpener @SessionGUID

সাবট্রি ব্যয়: 19.2

আমি দৌড়েছি

sp_recompile ViewOpener

এবং এটি এখনও একইভাবে (খারাপভাবে) চালায় এবং আমি সঞ্চিত পদ্ধতিটিও পরিবর্তিত করেছি

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *, 'recompile please'
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

এবং আবার ফিরে, সত্যিই এটি পুনরায় সংশোধন করার কৌশল।

আমি নতুন পরিকল্পনা উত্পন্ন করার জন্য সঞ্চিত পদ্ধতিটিকে বাদ দিয়ে পুনরায় তৈরি করেছি।

আমি একটি ডিকয় ভেরিয়েবল ব্যবহার করে পুনরায় কম্পাইল করার জন্য জোর করে চেষ্টা করেছি এবং পরামিতিগুলি স্নিফিং প্রতিরোধ করেছি :

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS

DECLARE @SessionGUIDbitch uniqueidentifier
SET @SessionGUIDbitch = @SessionGUID

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUIDbitch
ORDER BY CurrencyTypeOrder, Rank

আমি সঞ্চিত পদ্ধতিটিও সংজ্ঞায়িত করার চেষ্টা করেছি WITH RECOMPILE:

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE
AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

যাতে এর পরিকল্পনাটি কখনই ক্যাশে না হয় এবং আমি মৃত্যুদণ্ড কার্যকর করতে একটি পুনরায় কম্পাইল করার চেষ্টা করেছি:

EXECUTE ViewOpener @SessionGUID WITH RECOMPILE

যা সাহায্য করেনি।

আমি পদ্ধতিটি গতিশীল এসকিউএল রূপান্তর করার চেষ্টা করেছি:

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE AS
DECLARE @SQLString NVARCHAR(500)

SET @SQLString = N'SELECT *
   FROM Report_OpenerTest
   WHERE SessionGUID = @SessionGUID
   ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
N'@SessionGUID uniqueidentifier',
@SessionGUID

যা সাহায্য করেনি।

সত্তা " Report_Opener" একটি দর্শন, যা সূচিযুক্ত নয়। দৃশ্যটি কেবল অন্তর্নিহিত সারণীগুলি উল্লেখ করে। কোনও সারণীতে গণিত কলাম, সূচিযুক্ত বা অন্য কোনও উপায়ে নেই।

এর নরকের জন্য আমি এর সাথে ভিউ তৈরির চেষ্টা করেছি

SET ANSI_NULLS ON
SET QUOTED_IDENTIFER ON

এটি ঠিক করে নি।

এটা কেমন আছে

  • কোয়েরিটি দ্রুত is
  • ক্যোয়ারিকে একটি দৃশ্যে সরিয়ে নিয়ে যাওয়া এবং ভিউ থেকে নির্বাচন করা দ্রুত
  • সঞ্চিত পদ্ধতি থেকে ভিউ থেকে নির্বাচন করা 40x ধীর?

আমি দৃশ্যের সংজ্ঞাটি সরাসরি সঞ্চিত পদ্ধতিতে সরানোর চেষ্টা করেছি (3 টি ব্যবসায়িক বিধি লঙ্ঘন, এবং একটি গুরুত্বপূর্ণ এনক্যাপসুলেশন ভেঙে), এবং এটি কেবল প্রায় 6x ধীর করে তোলে।

কেন সঞ্চিত প্রক্রিয়া সংস্করণ এত ধীর? বিভিন্ন ধরণের অ্যাড-হক এসকিউএল এর চেয়ে দ্রুত এসকিউএল সার্ভারের জন্য অ্যাড-হক এসকিউএল দ্রুত চালিত হতে পারে?

আমি সত্যিই বরং না

  • কোডে এসকিউএল এম্বেড করুন
  • কোডটি একেবারে পরিবর্তন করুন

    Microsoft SQL Server  2000 - 8.00.2050 (Intel X86)
    Mar  7 2008 21:29:56
    Copyright (c) 1988-2003 Microsoft Corporation
    Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)

তবে কী কী জন্য এসকিউএল সার্ভার এসকিউএল সেভারের তত দ্রুত সঞ্চালন করতে অক্ষম হওয়ায় কী কী প্যারামিতি স্নিফিং হয় না।


আমার পরবর্তী প্রচেষ্টা অবশিষ্ট থাকবে হবে StoredProcedureAকল StoredProcedureBকল StoredProcedureCকল StoredProcedureDদৃশ্য ক্যোয়ারীতে।

এবং এটি ব্যর্থ হ'ল, সঞ্চিত পদ্ধতিতে কোনও সঞ্চিত পদ্ধতি কল করুন, একটি ইউডিএফ কল করুন, একটি ইউডিএফ কল করুন, একটি সঞ্চিত প্রক্রিয়া কল করুন, ভিউটিকে জিজ্ঞাসা করার জন্য কোনও ইউডিএফ কল করুন।


সংক্ষিপ্তসার হিসাবে, নিম্নলিখিত QA থেকে দ্রুত চালান, কিন্তু একটি সঞ্চিত পদ্ধতিতে রাখার সময় ধীরে ধীরে:

মূল:

--Runs fine outside of a stored procedure
SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

sp_executesql:

--Runs fine outside of a stored procedure
DECLARE @SQLString NVARCHAR(500)
SET @SQLString = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
        N'@SessionGUID uniqueidentifier',
        @SessionGUID

EXEC(@sql):

--Runs fine outside of a stored procedure
DECLARE @sql NVARCHAR(500)
SET @sql = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = '''+CAST(@SessionGUID AS varchar(50))+'''
ORDER BY CurrencyTypeOrder, Rank'

EXEC(@sql)

কার্যকর করার পরিকল্পনা

ভাল প্ল্যান:

      |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
           |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[CurrencyType]
                |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                     |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currencies].
                     |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                     |         |--Nested Loops(Left Outer Join)
                     |         |    |--Bookmark Lookup(BOOKMARK:([Bmk1016]), OBJECT:([GrobManagementSystemLive].[dbo].[Windows]))
                     |         |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Openers].[WindowGUID]))
                     |         |    |         |--Bookmark Lookup(BOOKMARK:([Bmk1014]), OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                     |         |    |         |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_SessionGUID]), SEEK:([Openers].[SessionGUID]=[@SessionGUID]) ORDERED FORWARD)
                     |         |    |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows]), SEEK:([Windows].[WindowGUID]=[Openers].[WindowGUID]) ORDERED FORWARD)
                     |         |    |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Currenc
                     |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                          |--Stream Aggregate(DEFINE:([Expr1006]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='ctCanadianCoin') OR [
                               |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                    |--Nested Loops(Inner Join)
                                    |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |    |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)

খারাপ পরিকল্পনা

       |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
            |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[Currency
                 |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                      |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currenc
                      |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                      |         |--Filter(WHERE:([Openers].[SessionGUID]=[@SessionGUID]))
                      |         |    |--Concatenation
                      |         |         |--Nested Loops(Left Outer Join)
                      |         |         |    |--Table Spool
                      |         |         |    |    |--Hash Match(Inner Join, HASH:([Windows].[WindowGUID])=([Openers].[WindowGUID]), RESIDUAL:([Windows].[WindowGUID]=[Openers].[WindowGUID]))
                      |         |         |    |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows_CageGUID]))
                      |         |         |    |         |--Table Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                      |         |         |    |--Table Spool
                      |         |         |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |         |--Compute Scalar(DEFINE:([Openers].[OpenerGUID]=NULL, [Openers].[SessionGUID]=NULL, [Windows].[UseChipDenominations]=NULL))
                      |         |              |--Nested Loops(Left Anti Semi Join)
                      |         |                   |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |                   |--Row Count Spool
                      |         |                        |--Table Spool
                      |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Cu
                      |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                           |--Stream Aggregate(DEFINE:([Expr1006]=SUM([partialagg1034]), [Expr1007]=SUM([partialagg1035]), [Expr1008]=SUM([partialagg1036]), [Expr1009]=SUM([partialagg1037]), [Expr1010]=SUM([partialagg1038]), [Expr1011]=SUM([partialagg1039]
                                |--Nested Loops(Inner Join)
                                     |--Stream Aggregate(DEFINE:([partialagg1034]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='
                                     |    |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                     |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)
                                     |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)

খারাপটি 6 মিলিয়ন সারিগুলিকে স্পুলিং করছে; অন্যটি না।

দ্রষ্টব্য: এটি কোনও ক্যোয়ারী টিউন করার বিষয়ে প্রশ্ন নয়। আমার কাছে একটি ক্যোয়ারী রয়েছে যা বজ্রপাত দ্রুত চালায়। আমি কেবল এসকিউএল সার্ভারটি একটি সঞ্চিত পদ্ধতি থেকে দ্রুত চালিত করতে চাই।


আমি প্রতিবার লক্ষ্য করেছি যে আপনি যখনই কোনও প্যারামিটার নিয়ে যান এবং অন্যটিকে এটি পুনরায় অর্পণ করেন এবং পরে এটি কোনও প্রশ্নে ব্যবহার করেন এটি পরে ঘটতে পারে এবং উত্তরটি যেমন "" সাম্প্রতিক নাম "এর জন্য অপ্টিমাইজ কাজ করতে পারে তেমন কাজ করতে পারে।
জাস্টডেভ

উত্তর:


404

মূল পোস্টার হিসাবে আমারও একই সমস্যা ছিল কিন্তু উদ্ধৃত উত্তরটি আমার জন্য সমস্যার সমাধান করতে পারেনি। সন্ধান করা পদ্ধতি থেকে ক্যোয়ারীটি এখনও ধীরে ধীরে চলছিল।

আমি এখানে আরও একটি উত্তর পেয়েছি "প্যারামিটার স্নিফিং" , ধন্যবাদ ওমনিবজ। আপনার সঞ্চিত পদ্ধতি প্রশ্নগুলিতে "স্থানীয় ভেরিয়েবলস" ব্যবহার করতে উত্সাহিত করে তবে আরও বোঝার জন্য মূলটি পড়ুন, এটি দুর্দান্ত লেখা। যেমন

ধীর পথ:

CREATE PROCEDURE GetOrderForCustomers(@CustID varchar(20))
AS
BEGIN
    SELECT * 
    FROM orders
    WHERE customerid = @CustID
END

দ্রুত উপায়:

CREATE PROCEDURE GetOrderForCustomersWithoutPS(@CustID varchar(20))
AS
BEGIN
    DECLARE @LocCustID varchar(20)
    SET @LocCustID = @CustID

    SELECT * 
    FROM orders
    WHERE customerid = @LocCustID
END

আশা করি এটি অন্য কাউকে সহায়তা করবে, এটি করার ফলে আমার মৃত্যুদন্ড কার্যকর হওয়ার সময়টি 5+ মিনিট থেকে প্রায় 6-7 সেকেন্ডে হ্রাস পেয়েছে।


23
+1 তবে এটি অত্যন্ত আশ্চর্যজনক এবং প্রচুর প্রশ্ন উত্থাপন করা উচিত যেমন আমাদের সমস্ত পদ্ধতির জন্য এটি করা উচিত এবং যদি না হয় তবে কখন এটি করা উচিত?
q

31
আমি কি একমাত্র এই আচরণে হতবাক ?? প্যারামিটার সান্ফিং প্রতিরোধের জন্য স্থানীয় ভেরিয়েবলগুলি ঘোষিত হওয়া প্রয়োজন ?? এসকিউএল সার্ভারটি প্রথমে এমনটি হতে না হতে পারে এমন স্মার্ট হওয়া উচিত? এটি কেবল মাইক্রোসফ্টের শর্টসাইটেড ডিজাইন আইএমএইচও দ্বারা অপ্রয়োজনীয় কোড ব্লোটার কারণ হয়ে দাঁড়ায়।
l46kok

4
15 মিনিট -> 8 সেকেন্ড! লাইফ সেভার
টনি ব্রিক্স

3
@ বনেটডিল WITH RECOMPILEআমার পক্ষে কোনও পার্থক্য তৈরি করেনি, কেবল স্থানীয় প্যারামিটার।
mrogers

8
বিকল্প (নিখুত জন্য (@varA অজানা, @varB অজানা) - এই এখন কোয়েরি ইঙ্গিতটি ব্যবহার অর্জন করা যেতে পারে
ডেভ

131

আমি সমস্যাটি পেয়েছি, এখানে সঞ্চিত পদ্ধতির ধীর এবং দ্রুত সংস্করণের স্ক্রিপ্টটি দেওয়া হয়েছে:

dbo.ViewOpener__RenamedForCruachan__Slow.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS OFF 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Slow
    @SessionGUID uniqueidentifier
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

dbo.ViewOpener__RenamedForCruachan__Fast.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Fast
    @SessionGUID uniqueidentifier 
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

আপনি যদি পার্থক্যটি চিহ্নিত না করেন, আমি আপনাকে দোষ দিচ্ছি না। পার্থক্য মোটেও সঞ্চিত পদ্ধতিতে নয়। এই পার্থক্যটি যা দ্রুত 0.5 দামের ক্যোয়ারিকে একটিতে রূপান্তর করে যা 6 মিলিয়ন সারিগুলির আগ্রহী স্পুল করে:

মন্থর: SET ANSI_NULLS OFF

ফাস্ট: SET ANSI_NULLS ON


এই উত্তরটিও বোঝার জন্য তৈরি করা যেতে পারে, যেহেতু ভিউটিতে একটি যোগদানের ধারা রয়েছে যা বলে:

(table.column IS NOT NULL)

তাই কিছু NULLজড়িত আছে।


ক্যোয়ারি অ্যানালাইজারে ফিরে এসে দৌড়ে ব্যাখ্যাটি আরও প্রমাণিত হয়েছে

SET ANSI_NULLS OFF

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

এবং ক্যোয়ারী ধীর।


সুতরাং সমস্যাটি নয় কারণ একটি সঞ্চিত পদ্ধতি থেকে ক্যোয়ারী চালানো হচ্ছে। সমস্যাটি হল এন্টারপ্রাইজ ম্যানেজারের সংযোগের ডিফল্ট বিকল্পটি ANSI_NULLS offবরং ANSI_NULLS onQA এর ডিফল্ট।

মাইক্রোসফ্ট KB296769 এ সত্যটি স্বীকার করে ( বিইউজি : লিঙ্কযুক্ত সার্ভার অবজেক্টসযুক্ত স্টোরেজ পদ্ধতি তৈরি করতে এসকিউএল এন্টারপ্রাইজ ম্যানেজার ব্যবহার করতে পারে না)। সক্রিয় ANSI_NULLSপদ্ধতি সংলাপের মধ্যে বিকল্পটি অন্তর্ভুক্ত করে :

Set ANSI_NULLS ON
Go
Create Proc spXXXX as
....

2
আমি এখনও বুঝতে পারি না যে ঘুরিয়ে দেওয়া ANSI_NULLS ONযেমন একটি বিশাল পারফরম্যান্সের পার্থক্য করে।
জাস্টিন হেলগারসন

2
@ Ek0nomik কারণ ভিউটির JOINঅভ্যন্তরীণ ধারাগুলির কখন আলাদা অর্থ রয়েছে ANSI_NULLS OFF। হঠাৎ সারিগুলি মিলবে, যার ফলে অপ্টিমাইজারটি কোয়েরিকে সম্পূর্ণ ভিন্নভাবে চালিত করবে। কল্পনা করুন যে সমস্ত সারিগুলির 99.9% মুছে ফেলার পরিবর্তে তারা হঠাৎ ফিরে আসবে।
ইয়ান বয়ড

2
দ্রষ্টব্য: ANSI_NULLS OFFঅবহেলিত এবং একটি খারাপ অনুশীলন হিসাবে বিবেচনা করা হয়
জিন

2
লিঙ্ক "এসকিউএল সার্ভারের ভবিষ্যতের সংস্করণে, এএনএসআই_এনএলএলএস সর্বদা চালু থাকবে এবং যে অ্যাপ্লিকেশনগুলি স্পষ্টভাবে বন্ধ করার বিকল্পটি সেট করেছে তা একটি ত্রুটি তৈরি করবে new নতুন বিকাশের কাজে এই বৈশিষ্ট্যটি ব্যবহার করা থেকে বিরত থাকুন এবং বর্তমানে এই বৈশিষ্ট্যটি ব্যবহার করে এমন অ্যাপ্লিকেশনগুলিকে সংশোধন করার পরিকল্পনা করুন। "
সটন

আমার ক্ষেত্রে সাহায্য করেনি।
st_stefanov

19

আপনার ডাটাবেসের জন্য এটি করুন। আমার একই সমস্যা রয়েছে - এটি একটি ডাটাবেসে সূক্ষ্মভাবে কাজ করে তবে যখন আমি এসএসআইএস আমদানি (সাধারণ পুনরুদ্ধার নয়) ব্যবহার করে এই ডাটাবেসটিকে অন্যটিতে অনুলিপি করি তখন আমার বেশিরভাগ সঞ্চিত পদ্ধতিতে এই সমস্যাটি ঘটে। কিছুটা গুগল করার পরে, আমি পিনাল ডেভের ব্লগটি পেয়েছি (যা বিটিডব্লিউ, আমি তার পোস্টটির বেশিরভাগ মুখোমুখি হয়েছি এবং আমাকে অনেক সাহায্য করেছিল তাই পিনাল ডেভকে ধন্যবাদ)

আমি আমার ডাটাবেসে নীচের প্রশ্নটি সম্পাদন করি এবং এটি আমার সমস্যাটিকে সংশোধন করে:

EXEC sp_MSforeachtable @command1="print '?' DBCC DBREINDEX ('?', ' ', 80)"
GO
EXEC sp_updatestats
GO 

আশাকরি এটা সাহায্য করবে. আমাকে সাহায্যকারী অন্যের কাছ থেকে কেবল সহায়তাটি পাস করা।


2
ভবিষ্যতের পাঠকদের জন্য কেবল একটি এফওয়াইআই: হ্রাস DBCC REINDEXকরা হয়েছে, সুতরাং আপনার বিকল্পগুলির সন্ধান করা উচিত।
মিনিটে মার্ভে গেভ করুন

1
আমার সমস্যা সমাধান করুন, ধন্যবাদ (1m20s 2s থেকে নীচে!)। পুনরায় DBCC DBREINDEX, এমএস বলেছেন: "মাইক্রোসফ্ট এসকিউএল সার্ভারের ভবিষ্যতের সংস্করণে এই বৈশিষ্ট্যটি সরানো হবে new নতুন উন্নয়ন কাজে এই বৈশিষ্ট্যটি ব্যবহার করবেন না এবং বর্তমানে যত তাড়াতাড়ি সম্ভব এই বৈশিষ্ট্যটি ব্যবহার করে এমন অ্যাপ্লিকেশনগুলিকে সংশোধন করুন instead পরিবর্তে অল্টার আইএনডিএক্স ব্যবহার করুন।"
AjV Jsy

এটি সেরা উত্তর কিনা তা জানেন না তবে আমার ক্ষেত্রে এসপি_প্যাডেস্ট্যাটসগুলি এটি সমস্ত গ্রহণ করেছে, সুতরাং +1
টড মেনিয়ার

..আজ এবং, ভুলে যাবেন না যে পুনর্নির্মাণ সূচীগুলিতে সময় এবং স্থান লাগতে পারে তাই আপনার প্রোডাকশন সার্ভারে এটি কার্যকর করার আগে নিশ্চিত হয়ে নিন যে আপনি সম্ভাব্য মন্দার সামর্থ্য পারবেন। আমি পুনর্গঠন করতে বা পুনরায় বিল্ড করার পরামর্শ দেব (অনলাইনে = চালু)
মিলান

14

আমি একই সমস্যার মুখোমুখি হয়েছি এবং এই পোস্টটি আমার পক্ষে খুব সহায়ক ছিল তবে পোস্ট করা উত্তরগুলির মধ্যে কোনওই আমার নির্দিষ্ট সমস্যাটির সমাধান করেনি। আমি যে সমাধানটি আমার পক্ষে কাজ করেছে তা পোস্ট করতে চেয়েছিলাম যে এটি অন্য কাউকে সহায়তা করতে পারে।

https://stackoverflow.com/a/24016676/814299

আপনার ক্যোয়ারির শেষে, অপশনটি যুক্ত করুন (এর জন্য অপ্টিমাইজ করুন (@ অজানা জানা))


4

এবার আপনি নিজের সমস্যাটি খুঁজে পেয়েছেন। যদি পরের বার আপনি কম ভাগ্যবান হন এবং এটি নির্ধারণ করতে না পারেন তবে আপনি পরিকল্পনা হিমশীতল ব্যবহার করতে পারেন এবং ভুল কার্যকরকরণ পরিকল্পনার বিষয়ে চিন্তা করা বন্ধ করতে পারেন ।


সেই ব্লগ এন্ট্রি অনুসারে, পরিকল্পনা হিমায়ন কেবলমাত্র এমএস এসকিউএল 2005 এবং তারপরের জন্য, সুতরাং এটি ওপিকে সহায়তা করবে না।
কক্সি

সমস্যাটি ছিল এটি ভুল কোয়েরি প্ল্যানটি ব্যবহার করছিল। আমি এটিকে ভুলতে স্থির করতে চাই না।
ইয়ান বয়ড

4

আমি এই সমস্যাটি অনুভব করছিলাম। আমার ক্যোয়ারিতে এমন কিছু লাগছিল:

select a, b, c from sometable where date > '20140101'

আমার সঞ্চিত পদ্ধতিটি এর মতো সংজ্ঞায়িত হয়েছিল:

create procedure my_procedure (@dtFrom date)
as
select a, b, c from sometable where date > @dtFrom

আমি ডেটাটাইপটি ডেটটাইম এবং ভয়েলায় পরিবর্তিত করেছি! 30 মিনিট থেকে 1 মিনিট পর্যন্ত চলে গেছে!

create procedure my_procedure (@dtFrom datetime)
as
select a, b, c from sometable where date > @dtFrom

2
ধন্যবাদ লট লি, এটি আমার দিনটি বাঁচিয়েছে! একটি তারিখের ক্ষেত্রের কেবলমাত্র তারিখের অংশটি আমি কীভাবে এখানে পেয়েছি তা এখানে: DATEADD (dd, 0, DATEDIFF (dd, 0, table.field))
জুলিয়ান বি

1
এটি আমার সমস্যা সমাধান করেছে। আমার কলাম ভারচার (২০) ছিল এবং আমার প্যারামিটারটি নওয়ারচর (50) ছিল, আমি একবার প্যারামিটারটি কলামের ধরণের মতো করে দিয়েছিলাম - আর কোনও বিলম্ব নেই।
st_stefanov

3

আপনি কি রিপোর্ট_অপনার টেবিলে পরিসংখ্যান এবং / অথবা সূচীগুলি পুনর্নির্মাণের চেষ্টা করেছেন? ডেটাবেস প্রথম উদ্বোধনকালে পরিসংখ্যানগুলি এখনও ডেটা দেখায় যদি এসপির সমস্ত পুনঃনির্মাণগুলি মূল্যহীন হবে না।

প্রাথমিক ক্যোয়ারী নিজেই দ্রুত কাজ করে কারণ অপ্টিমাইজারটি দেখতে পারে যে প্যারামিটারটি কখনই শূন্য হবে না। এসপির ক্ষেত্রে অপটিমাইজার নিশ্চিত হতে পারে না যে প্যারামিটারটি কখনই শূন্য হবে না।


কোনও স্টোরেজ পদ্ধতি ঘোষণায় ইঙ্গিত করার কোনও উপায় আছে যে আমি প্যারামিটারটি বাতিল হতে পারে না? এবং এটি কি এমন কিছু নয় যা sp_executesql দ্বারা স্থির হবে?
ইয়ান বয়ড

একটি কথায় কথায় না, 2000 সালে নয়। 2005 একটি ক্যোয়ারির ইঙ্গিত যুক্ত করেছে যেখানে আপনি প্যারামিটারের জন্য উদাহরণের মান সরবরাহ করতে পারেন, অপটিমাইজারটি এমনভাবে অনুকূলিত হবে যেন এটি যদি জানত যে প্যারামিটারটি সর্বদা ব্যবহৃত হয়েছিল। এই বলে যে আমি সাধারণত এই ধরণের জিনিসটিকে একটি পরিসংখ্যানের সমস্যা বলে মনে করেছি।
অ্যান্থনিডাব্লু জোন্স

যদি এটি কোনও পরিসংখ্যানের সমস্যা হয় তবে আমি যখন এটিকে এড-হক, এসপি_সেকিউটসকিএল, এক্সিকিউটিভ () চালনা করি তখন তারা কিউএ থেকে সূক্ষ্মভাবে কাজ করে। এবং কেন তারা সমস্ত তখন খারাপভাবে চালায় যখন কোনও সঞ্চিত পদ্ধতিতে অ্যাড-হক স্কেল, এসপি_এক্সেকটসকিএল, এক্সিকিউটিভ () থাকে?
ইয়ান বয়ড

1

যদিও আমি সাধারণত এর বিপক্ষে (যদিও এই ক্ষেত্রে মনে হয় যে আপনার আসল কারণ আছে), আপনি কি কোয়েরিটির এসপি সংস্করণে কোনও কোয়েরি ইঙ্গিত দেওয়ার চেষ্টা করেছেন? যদি এসকিউএল সার্ভার এই দুটি ক্ষেত্রে পৃথক সম্পাদন পরিকল্পনা প্রস্তুত করে, আপনি কোন সূচকটি ব্যবহার করবেন তা বলার জন্য কোনও ইঙ্গিত ব্যবহার করতে পারেন, যাতে পরিকল্পনাটি প্রথমটির সাথে মেলে?

কিছু উদাহরণের জন্য, আপনি এখানে যেতে পারেন

সম্পাদনা: আপনি যদি এখানে আপনার ক্যোয়ারী পরিকল্পনা পোস্ট করতে পারেন তবে সম্ভবত আমরা যে পরিকল্পনাগুলি বলছি তার মধ্যে কিছু পার্থক্য সনাক্ত করতে পারি।

দ্বিতীয়: লিঙ্কটি এসকিউএল -2000 নির্দিষ্ট করার জন্য আপডেট করেছে। আপনাকে কোনও উপায়ে স্ক্রোল করতে হবে, তবে একটি দ্বিতীয় শিরোনাম আছে "টেবিল ইঙ্গিত" যা আপনি সন্ধান করছেন।

থার্ড: "খারাপ" ক্যোয়ারী "ওপেনার্স" টেবিলের [আইএক্স_অপেনার্সসেশনজিউইডি] উপেক্ষা করছে বলে মনে হচ্ছে - কোনও সূচককে এই সূচকটি ব্যবহার করতে বাধ্য করার জন্য কোনও ইন্ডেক্স ইঙ্গিত যুক্ত করার ফলে কি জিনিসগুলি পরিবর্তিত হবে?


সেই রেফারেন্সে সর্বাধিক দরকারী ক্যোয়ারী ইঙ্গিতগুলি এসকিউএল 2000 এ উপলভ্য নয় যা এখানে প্রশ্নের সংস্করণ।
অ্যান্থনিডাব্লু জোনস

অতিরিক্তভাবে, কী ইঙ্গিতগুলির প্রয়োজন? এসকিউএল সার্ভার যখন আমি এড-হক চালাচ্ছি তখন এটি কোনও সমস্যা নির্ধারণ করতে সক্ষম।
ইয়ান বয়ড

অবশ্যই, এবং এটি আমার অভিজ্ঞতাও বরাবরই ছিল। তবে, এক্ষেত্রে তিনি বলছেন এটি সম্পূর্ণ ভিন্ন নির্বাহী পরিকল্পনা নিয়ে আসছে। হতে পারে এমন একটি সূচক রয়েছে যা অ্যাড-হক ব্যবহার করেছে, তবে কোনও কারণে প্রকোপটিতে উপেক্ষা করা হচ্ছে। তিনি এসকিউএল সার্ভারকে "INDEX" ইঙ্গিত সহ সূচকটি ব্যবহার করতে বাধ্য করতে পারেন।
স্কাল্লায়ান

1

এটি সম্ভবত অসম্ভব, তবে আপনার পর্যবেক্ষণ করা আচরণটি অস্বাভাবিক হওয়ার কারণে এটি পরীক্ষা করা দরকার এবং অন্য কেউ এটি উল্লেখ করেননি।

তুমি কি একেবারে? নিশ্চিত করুন যে সমস্ত বস্তু dbo মালিকানা রয়েছে এবং আপনি নিজের বা পাশাপাশি একজন আলাদা ব্যবহারকারীতে বর্তমান মালিকানাধীন একটি দুর্বৃত্ত কপি নেই?

মাঝে মাঝে যখন আমি অদ্ভুত আচরণ দেখেছি তা কারণ এটি আসলে কোনও বস্তুর দুটি অনুলিপি ছিল এবং কোনটি আপনি পেয়েছেন তা নির্দিষ্ট করা হয়েছে এবং আপনি কাকে লগ ইন করেছেন তার উপর নির্ভর করে। উদাহরণস্বরূপ একই নাম সহ ভিউ বা পদ্ধতির দুটি অনুলিপি থাকা সম্পূর্ণ ভিন্ন তবে পৃথক মালিকদের মালিকানাধীন - এমন একটি পরিস্থিতি তৈরি হতে পারে যেখানে আপনি ডিবেও হিসাবে ডেটাবেজে লগইন না করে এবং ডিবিওকে অবজেক্টের মালিক হিসাবে নির্দিষ্ট করতে ভুলে যেতে পারেন আপনি অবজেক্ট তৈরি করুন।

উল্লেখ্য যে পাঠ্যে আপনি মালিককে নির্দিষ্ট করে না রেখে কিছু জিনিস চালাচ্ছেন

sp_recompile ViewOpener

উদাহরণস্বরূপ, সেখানে যেখানে ডিবিওর মালিকানাধীন ভিউ-ওপেনারের দুটি অনুলিপি এবং [অন্য কোনও ব্যবহারকারীর] তারপরে যদি আপনি নির্দিষ্ট না করেন তবে কোনটি আপনি আসলে পুনরায় সংকলন করেন তা পরিস্থিতি নির্ভর। রিপোর্ট_অপনার দৃশ্যের সাথে ডিট্টো - সেখানে যদি দুটি কপি থাকে (এবং সেগুলি নির্দিষ্টকরণ বা সম্পাদনের পরিকল্পনায় পৃথক হতে পারে) তবে কী ব্যবহার করা হয় তা পরিস্থিতিগুলির উপর নির্ভর করে - এবং আপনি মালিককে নির্দিষ্ট না করে নিলে এটি ঠিক সম্ভব যে আপনার অ্যাডহক ক্যোয়ারী একটি এবং এটি ব্যবহার করতে পারে সংকলিত পদ্ধতিটি অন্যটি ব্যবহার করতে পারে।

আমি যেমন বলেছি এটি সম্ভবত অসম্ভব তবে এটি সম্ভব এবং এটি পরীক্ষা করা উচিত কারণ আপনার সমস্যাগুলি এমন হতে পারে যে আপনি কেবল ভুল জায়গায় বাগটি খুঁজছেন।


1

এটি নির্বোধ শোনায় এবং সেশনগিউইডি নামটি থেকে সুস্পষ্ট মনে হতে পারে তবে কলামটি কি রিপোর্ট_অপেনারের অনন্য পরিচয়দাতা? যদি তা না হয় তবে আপনি এটি সঠিক ধরণের toালতে চেষ্টা করতে পারেন এবং এটিকে একটি শট দিতে পারেন বা আপনার পরিবর্তনশীলটিকে সঠিক ধরণের হিসাবে ঘোষণা করতে পারেন।

স্প্রোকের অংশ হিসাবে তৈরি করা পরিকল্পনাটি অনিচ্ছাকৃতভাবে কাজ করতে পারে এবং বড় টেবিলের অভ্যন্তরীণ কাস্ট করতে পারে।


এইটা না. তবে আমি এমন একটি ধারাটিতে পারফরম্যান্স সমস্যা দেখেছি যেখানে একটি varcharকলামের সাথে একটি nvarcharমান (উদাহরণ WHERE CustomerName = N'zrendall') দিয়ে তুলনা করা হচ্ছে । এসকিউএল সার্ভারকে nvarcharতুলনার আগে প্রতিটি কলাম মানকে একটিতে রূপান্তর করতে হয়েছিল।
ইয়ান বয়ড

0

আমি অন্য ধারণা পেয়েছি। আপনি যদি এই টেবিল-ভিত্তিক ফাংশনটি তৈরি করেন:

CREATE FUNCTION tbfSelectFromView
(   
    -- Add the parameters for the function here
    @SessionGUID UNIQUEIDENTIFIER
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT *
    FROM Report_Opener
    WHERE SessionGUID = @SessionGUID
    ORDER BY CurrencyTypeOrder, Rank
)
GO

এবং তারপরে নীচের বিবৃতিটি ব্যবহার করে এটি থেকে নির্বাচন করা হয়েছে (এমনকি এটি আপনার এসপিতে রেখে দেওয়া):

SELECT *
FROM tbfSelectFromView(@SessionGUID)

দেখে মনে হচ্ছে যা হচ্ছে (যা প্রত্যেকে ইতিমধ্যে মন্তব্য করেছে) এটি হ'ল এসকিউএল সার্ভারটি কোথাও ভুল হিসাবে অনুমান করেছে এবং সম্ভবত এটি অনুমানটি সংশোধন করতে বাধ্য করবে। আমি অতিরিক্ত পদক্ষেপ যুক্ত করতে ঘৃণা করি, তবে আমি নিশ্চিত নই যে এর ফলে আর কী ঘটতে পারে।


0

- সমাধান এখানে:

create procedure GetOrderForCustomers(@CustID varchar(20))

as

begin

select * from orders

where customerid = ISNULL(@CustID, '')

end

-- এটাই

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.