এসকিউএল সার্ভারে "কোন যোগদানের পূর্বাভাস" এর অর্থ কী?


23

এমএসডিএন " অনুপস্থিত ইভেন্টের ক্লাস অনুপস্থিত " বলেছে এটি " ইঙ্গিত দেয় যে এমন একটি ক্যোয়ারী কার্যকর করা হচ্ছে যার কোনও যোগসূত্র নেই "।

তবে দুর্ভাগ্যক্রমে এটি এতটা সহজ বলে মনে হয় না।

উদাহরণস্বরূপ, খুব সাধারণ পরিস্থিতি:

create table #temp1(i int);
create table #temp2(i int);
Select * from #temp1, #temp2 option (recompile);

টেবিলগুলিতে কোনও ডেটা নেই, কোনও সতর্কতাও নেই, যদিও এটির স্পষ্টত কোনও যোগসূত্র নেই।

যদি আমি এসকিউএল সার্ভার 2005 (একই লিঙ্কটি, কেবলমাত্র অন্য সার্ভার সংস্করণ) এর জন্য ডকুমেন্টেশনগুলি দেখে নিই, তবে একটি অতিরিক্ত বাক্য রয়েছে: " যোগদানের উভয় পক্ষই যদি একাধিক সারিতে ফিরে আসে তবে এই ইভেন্টটি তৈরি করা হয় This " এটি তৈরি করবে পূর্ববর্তী পরিস্থিতিতে নিখুঁত জ্ঞান। কোনও ডেটা নেই, সুতরাং উভয় পক্ষই 0 টি সারি এবং কোনও সতর্কবার্তা দেয় না। সারি সন্নিবেশ করান, সতর্কতা পান। ঠিক আছে শান্ত হও.

তবে পরবর্তী বিভ্রান্তিকর পরিস্থিতির জন্য, আমি উভয় টেবিলে একই মান সন্নিবেশ করলাম:

Insert into #temp1 (i) values (1)
Insert into #temp1 (i) values (1)
Insert into #temp2 (i) values (1)
Insert into #temp2 (i) values (1)

এবং আমি পেয়েছি:

-- no warning:
Select * from #temp1 t1 
    inner join #temp2 t2 on t1.i = t2.i 
option (recompile)
-- has warning:
Select * from #temp1 t1 
    inner join (select 1 i union all select 1) t2 on t1.i = t2.i 
option (recompile)

কেন এমন হয়?

দ্রষ্টব্য : আমার সার্ভারে এই খারাপ কোয়েরিগুলি সনাক্ত করতে আমি ব্যবহৃত কিছু স্ক্রিপ্ট।

  1. অবশ্যই, পদ্ধতি কার্যকর করার পরিকল্পনা
  2. সতর্কতা পেতে ডিফল্ট সার্ভার ট্রেস ব্যবহার করেছেন

    Declare @trace nvarchar(500);
    Select @trace = cast(value as nvarchar(500))
    From sys.fn_trace_getinfo(Null)
    Where traceid = 1 and property = 2;
    
    Select t.StartTime, te.name, *
    From sys.fn_trace_gettable(@trace, 1) t
        Inner join sys.trace_events te on t.EventClass = te.trace_event_id
        where EventClass = 80
    order by t.StartTime desc
    
  3. সতর্কতা সহ এই পরিকল্পনাগুলি অনুসন্ধানের জন্য এক্সিকিউশন প্ল্যান ক্যাশে, (এটির মতো)

    WITH XMLNAMESPACES (default 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
    SELECT
        Cast('<?SQL ' + st.text + ' ?>' as xml) sql_text,
        pl.query_plan,
        ps.execution_count,
        ps.last_execution_time,
        ps.last_elapsed_time,
        ps.last_logical_reads,
        ps.last_logical_writes
    FROM sys.dm_exec_query_stats ps with (NOLOCK)
        Cross Apply sys.dm_exec_sql_text(ps.sql_handle) st
        Cross Apply sys.dm_exec_query_plan(ps.plan_handle) pl
    WHERE pl.query_plan.value('(//Warnings/@NoJoinPredicate)[1]', 'bit') = 1
    Order By last_execution_time desc
    OPTION (RECOMPILE);
    

উত্তর:


17

আপনার প্রশ্নটি অনুরূপ এই এক । কখনও কখনও এসকিউএল সার্ভার আসল কোয়েরি থেকে একটি যোগদানের প্রাকটিকেট সরিয়ে ফেলতে পারে।

আপনি যখন একটি জয়েন প্রিকিটিক সতর্কবার্তাটি দেখেন সে ক্ষেত্রে এসকিউএল সার্ভার সংকলনের সময় সনাক্ত করে যে ধ্রুবকগুলির সারণির কেবল একটি স্বতন্ত্র মান রয়েছে এবং সেই মানটি 1তাই ক্যোয়ারীটিকে আবার লিখেছে

SELECT *
FROM   (SELECT *
        FROM   #temp1 t1
        WHERE  t1.i = 1) t1
       CROSS JOIN (SELECT 1 i
                   UNION ALL
                   SELECT 1) t2 

সেখানে টেবিল স্ক্যান উপর একটি বিধেয় হয় #tempনিম্নরূপ[tempdb].[dbo].[#temp1].[i] =(1)

on t1.i = t2.iদুটি টেবিল ব্যবহার করার সময় বা কনস্ট্যান্টের টেবিলের একাধিক স্বতন্ত্র মান থাকলে সংকলনের সময় এইভাবে যোগদানের প্রাকটিকেটটি সরানো যায় না।


এই সম্পর্কে আরও তথ্য পাওয়া যাবে পল হোয়াইট 'এর ক্যোয়ারী অপ্টিমাইজার ডীপ ডাইভ সিরিজ।

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