Oracle <> , != , ^= operators

后端 未结 4 1361
孤街浪徒
孤街浪徒 2020-12-03 08:24

I want to know the difference of those operators, mainly their performance difference.

I have had a look at Difference between <> and != in SQL, it has no perf

4条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-03 08:59

    The writer of the article, although a book author and the purveyor of some useful information, does not have a good reputation for accuracy. In this case the article was merely a mention of one persons observations on a well known Oracle mailing list. If you read through the responses you will see the assumptions of the post challenged, but no presumption of accuracy. Here are some excerpts:

    Try running your query through explain plan (or autotrace) and see what that says... According to this, "!=" is considered to be the same as "<>"... Jonathan Lewis

    Jonathan Lewis is a well respected expert in the Oracle community.

    Just out of curiosity... Does the query optimizer generate a different execution plan for the two queries? Regards, Chris

    .

    Might it be bind variable peeking in action? The certain effect of writing != instead of <> is to force a re-parse. If at the first execution the values for :id were different and if you have an histogram on claws_doc_id it could be a reason. And if you tell me that claws_doc_id is the primary key, then I'll ask you what is the purpose of counting, in particular when the query in the EXISTS clause is uncorrelated with the outer query and will return the same result whatever :id is. Looks like a polling query. The code surrounding it must be interesting.

    Stéphane Faroult

    .

    I'm pretty sure the lexical parse converts either != to <> or <> to !=, but I'm not sure whether that affects whether the sql text will match a stored outline.

    .

    Do the explain plans look the same? Same costs?

    The following response is from the original poster.

    Jonathan, Thank you for your answer. We did do an explain plan on both versions of the statement and they were identical, which is what is so puzzling about this. According to the documentation, the two forms of not equal are the same (along with ^= and one other that I can't type), so it makes no sense to me why there is any difference in performance.

    Scott Canaan

    .

    Not an all inclusive little test but it appears at least in 10.1.0.2 it gets pared into a "<>" for either (notice the filter line for each plan)

    .

    Do you have any Stored Outline ? Stored Outlines do exact (literal) matches so if you have one Stored Outline for, say, the SQL with a "!=" and none for the SQL with a "<>" (or a vice versa), the Stored Outline might be using hints ? (although, come to think of it, your EXPLAIN PLAN should have shown the hints if executing a Stored Outline ?)

    .

    Have you tried going beyond just explain & autotrace and running a full 10046 level 12 trace to see where the slower version is spending its time? This might shed some light on the subject, plus - be sure to verify that the explain plans are exactly the same in the 10046 trace file (not the ones generated with the EXPLAIN= option), and in v$sqlplan. There are some "features" of autotrace and explain that can cause it to not give you an accurate explain plan.

    Regards, Brandon

    .

    Is the phenomenon totally reproducible ?

    Did you check the filter_predicates and access_predicates of the plan, or just the structure. I don't expect any difference, but a change in predicate order can result in a significant change in CPU usage if you are unlucky.

    If there is no difference there, then enable rowsource statistics (alter session set "_rowsource_execution_statistics"=true) and run the queries, then grab the execution plan from V$sql_plan and join to v$sql_plan_statistics to see if any of the figures about last_starts, last_XXX_buffer_gets, last_disk_reads, last_elapsed_time give you a clue about where the time went.

    If you are on 10gR2 there is a /*+ gather_plan_statistics */ hint you can use instead of the "alter session".

    Regards Jonathan Lewis

    At this point the thread dies and we see no further posts from the original poster, which leads me to believe that either the OP discovered an assumption they had made that was not true or did no further investigation.

    I will also point out that if you do an explain plan or autotrace, you will see that the comparison is always displayed as <>.

    Here is some test code. Increase the number of loop iterations if you like. You may see one side or the other get a higher number depending on the other activity on the server activity, but in no way will you see one operator come out consistently better than the other.

    DROP TABLE t1;
    DROP TABLE t2;
    CREATE TABLE t1 AS (SELECT level c1 FROM dual CONNECT BY level <=144000);
    CREATE TABLE t2 AS (SELECT level c1 FROM dual CONNECT BY level <=144000);
    
    SET SERVEROUTPUT ON FORMAT WRAPPED
    
    DECLARE
       vStart  Date;
       vTotalA Number(10) := 0;
       vTotalB Number(10) := 0;
       vResult Number(10);
    BEGIN   
       For vLoop In 1..10 Loop
          vStart := sysdate;
          For vLoop2 In 1..2000 Loop
             SELECT count(*) INTO vResult FROM t1 WHERE t1.c1 = 777 AND EXISTS
                (SELECT 1 FROM t2 WHERE t2.c1 <> 0);
          End Loop;
          vTotalA := vTotalA + ((sysdate - vStart)*24*60*60);
    
          vStart := sysdate;
          For vLoop2 In 1..2000 Loop
             SELECT count(*) INTO vResult FROM t1 WHERE t1.c1 = 777 AND EXISTS
                (SELECT 1 FROM t2 WHERE t2.c1 != 0);
          End Loop;
          vTotalB := vTotalB + ((sysdate - vStart)*24*60*60);
    
          DBMS_Output.Put_Line('Total <>: ' || RPAD(vTotalA,8) || '!=: ' || vTotalB);
          vTotalA := 0;
          vTotalB := 0;
       End Loop;
    
    END;
    

提交回复
热议问题