Oracle: TOAD и свой софт - разные планы запросов и скорость
От: Neco  
Дата: 13.09.11 11:42
Оценка:
На одной и той же машине из под одного и того же аккаунта запускаю один и тот же запрос. Запрос внутри ссылается на синонимы из других схем (если это имеет значение). Из-под тоада (и из-под sqlplus) выполнение происходит за пару секунд. Из-под своей программки, написанной на дотнете — дольше минуты.
выходил на dba — мало чем помогли, посмотрели в каком-то вебном туле — сказали мне, что в случае программки запрос начинает выполняться параллельно и потоки друг другу мешают — но мне что-то не верится в это плюс собственно вопрос в том, а почему так происходит.
была мысль, что из-за библиотечки для дотнета. System.Data.OracleClient считается устаревшей. Пробовал ODP.Net — лучше не стало.
также есть сейчас подозрение, что может быть разные home используются. Тоад показывает два:
SOFTWARE\ORACLE (Oracle Root) 
  ORACLE_HOME_NAME:  
  ORACLE_HOME:  
  ORACLE_SID:  
  NLS_LANG:  
  SQLPATH:  
  LOCAL:  
  Home directory  does NOT exist! 
  Home is NOT valid! 
SOFTWARE\ORACLE\KEY_V102030 
  ORACLE_HOME_NAME:  v102030
  ORACLE_HOME:  C:\oracle\v102030
  ORACLE_SID:  
  NLS_LANG:  RUSSIAN_CIS.CL8MSWIN1251
  SQLPATH:  C:\oracle\v102030\dbs
  LOCAL:  
  C:\oracle\v102030\Bin exists. 
  C:\oracle\v102030\Bin is in PATH. 
  Client DLL:  C:\oracle\v102030\Bin\oci.dll
  Client Version:  10.2.0.3.0Patch2
  Home is valid.

хотя первый невалидный — не должен он использоваться. пробовал в реестре поставить oracle_home чтобы он стал валидным — ничего не изменилось.

запрос возвращает в частном случае три строки — т.е. распространённая причина, когда быстро вытягиваются только первые строки, а на самом деле всё очень долго — это не этот случай.

что может приводить к такому поведению? как продиагностировать точную причину? как это может быть, что сервер начинает себя вести по-разному в зависимости от клиента — ведь значит, что клиент должен какие-то переменные сессии выставлять, чтобы себя отличным сделать. где это посмотреть? dba могут определить только имя и id процесса.

P.S. попробовал ещё через Excel (ADODB.Connection msado28) и в дотнете, но через OdbcConnection — тоже быстро.
может быть всё что быстро работает — это через odbc? однако, тут почитал http://msdn.microsoft.com/en-us/library/ms810810.aspx oracle odbc вроде как устарела.

21.09.11 09:06: Перенесено модератором из '.NET' — TK
всю ночь не ем, весь день не сплю — устаю
Re: Oracle: TOAD и свой софт - разные планы запросов и скоро
От: Neco  
Дата: 13.09.11 12:23
Оценка:
Здравствуйте, Neco, Вы писали:

N>P.S. попробовал ещё через Excel (ADODB.Connection msado28) и в дотнете, но через OdbcConnection — тоже быстро.

N>может быть всё что быстро работает — это через odbc? однако, тут почитал http://msdn.microsoft.com/en-us/library/ms810810.aspx oracle odbc вроде как устарела.
интересный нюанс обнаружился.
если заменить все переменные на константы — то запрос также выполняется очень быстро. так что тесты с sqlplus и экселем можно считать несостоявшимися — я не знаю как там переменные всавлять в запрос, поэтому сразу писал с константами.
Т.е. итого:
.Net System.Data.Oracle, .Net ODP.Net — медленно
Toad, .Net Odbc — быстро
.Net System.Data.Oracle (используя константы) — тоже быстро
всю ночь не ем, весь день не сплю — устаю
Re: Oracle: TOAD и свой софт - разные планы запросов и скоро
От: e.slyusar  
Дата: 13.09.11 13:21
Оценка:
Покажите код, как вы запускаете запрос!
Re[2]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 14.09.11 04:01
Оценка:
Здравствуйте, e.slyusar, Вы писали:

ES>Покажите код, как вы запускаете запрос!



namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            var sw = new System.Diagnostics.Stopwatch();
        
            sw.Start();
            TestSystemData();
            sw.Stop();
            double system_data = sw.Elapsed.TotalSeconds;

            sw.Reset();
            sw.Start();
            TestSystemDataNoParams();
            sw.Stop();
            double system_data_no_params = sw.Elapsed.TotalSeconds;

            sw.Reset();
            sw.Start();
            TestOdbc();
            sw.Stop();
            double odbc = sw.Elapsed.TotalSeconds;

            MessageBox.Show(string.Format("system.data {0}, system.data (no params) {1}, odbc {2}", system_data, system_data_no_params, odbc));
        }

        private void TestSystemData() {
            using (var conn = new OracleConnection("Data Source=************; User ID=************;Password=*************;Persist Security Info=True;")) {

                var sb = new StringBuilder();
                sb.AppendLine("select t.id, t.name, t.is_active");
                sb.AppendLine("from v_cost_center_master t ");
                sb.AppendLine(" where (nvl(id, (select value from const where id_key='cc_for_orphans')) in (");
                sb.AppendLine("       select cco.cost_center");
                sb.AppendLine("    from v_cost_center_owners cco");
                sb.AppendLine("    where cco.actual_owner_badge = :approver_badge");
                sb.AppendLine("    and nvl(cco.doa_case_id_key,'-') <> :self_doa_partial");
                sb.AppendLine(")");
                sb.AppendLine(") and (id in (");
                sb.AppendLine("    select org_cost_center");
                sb.AppendLine("    from v_sb_snap_full");
                sb.AppendLine("    where renewal_id=:renewal_id");
                sb.AppendLine(")");
                sb.AppendLine(")");
                sb.AppendLine("order by t.id asc");

                conn.Open();
                using (var cmd = conn.CreateCommand()) {
                    cmd.CommandText = sb.ToString();
                    AddParam(cmd, "approver_badge", DbType.Int32, 10121543);
                    AddParam(cmd, "self_doa_partial", DbType.String, "self_doa_partial");
                    AddParam(cmd, "renewal_id", DbType.Int32, 6);

                    using (var adap = new OracleDataAdapter(cmd)) {
                        var tbl = new DataTable();
                        adap.Fill(tbl);
                    }

                }

            }
        }

        private void TestSystemDataNoParams() {
            using (var conn = new OracleConnection("Data Source=**********; User ID=************;Password=************;Persist Security Info=True;")) {

                var sb = new StringBuilder();
                sb.AppendLine("select t.id, t.name, t.is_active");
                sb.AppendLine("from v_cost_center_master t ");
                sb.AppendLine(" where (nvl(id, (select value from const where id_key='cc_for_orphans')) in (");
                sb.AppendLine("       select cco.cost_center");
                sb.AppendLine("    from v_cost_center_owners cco");
                sb.AppendLine("    where cco.actual_owner_badge = 10121543");
                sb.AppendLine("    and nvl(cco.doa_case_id_key,'-') <> 'self_doa_partial'");
                sb.AppendLine(")");
                sb.AppendLine(") and (id in (");
                sb.AppendLine("    select org_cost_center");
                sb.AppendLine("    from v_sb_snap_full");
                sb.AppendLine("    where renewal_id=6");
                sb.AppendLine(")");
                sb.AppendLine(")");
                sb.AppendLine("order by t.id asc");

                conn.Open();
                using (var cmd = conn.CreateCommand()) {
                    cmd.CommandText = sb.ToString();

                    using (var adap = new OracleDataAdapter(cmd)) {
                        var tbl = new DataTable();
                        adap.Fill(tbl);
                    }

                }

            }
        }
        private void TestOdbc() {
            using (var conn = new OdbcConnection("DSN=*****; UID=**********;PWD=************;")) {

                var sb = new StringBuilder();
                sb.AppendLine("select t.id, t.name, t.is_active");
                sb.AppendLine("from v_cost_center_master t ");
                sb.AppendLine(" where (nvl(id, (select value from const where id_key='cc_for_orphans')) in (");
                sb.AppendLine("       select cco.cost_center");
                sb.AppendLine("    from v_cost_center_owners cco");
                sb.AppendLine("    where cco.actual_owner_badge = ?");
                sb.AppendLine("    and nvl(cco.doa_case_id_key,'-') <> ?");
                sb.AppendLine(")");
                sb.AppendLine(") and (id in (");
                sb.AppendLine("    select org_cost_center");
                sb.AppendLine("    from v_sb_snap_full");
                sb.AppendLine("    where renewal_id=?");
                sb.AppendLine(")");
                sb.AppendLine(")");
                sb.AppendLine("order by t.id asc");

                conn.Open();
                using (var cmd = conn.CreateCommand()) {
                    cmd.CommandText = sb.ToString();
                    AddParam(cmd, "approver_badge", DbType.Int32, 10121543);
                    AddParam(cmd, "self_doa_partial", DbType.String, "self_doa_partial");
                    AddParam(cmd, "renewal_id", DbType.Int32, 6);
                    //cmd.Parameters.Add(CreateParam("approver_badge", DbType.Int32, 10121543));
                    //cmd.Parameters.Add(CreateParam("self_doa_partial", DbType.String, "self_doa_partial"));
                    //AddParam(cmd, "renewal_id", DbType.Int32, 6);

                    int rez = cmd.ExecuteNonQuery();
                }

            }
        }

        private static void AddParam(IDbCommand cmd, string name, DbType type, object value) {
            IDbDataParameter rez = cmd.CreateParameter();
            rez.ParameterName = name;
            rez.DbType = type;
            rez.Value = value;
            cmd.Parameters.Add(rez);
        }

    }
}


результаты
первого запуска: system.data 182.9845882, system.data (no params) 6.5533367, odbc 18.4702151
второго запуска: system.data 166.2260324, system.data (no params) 0.8451689, odbc 4.6515252
всю ночь не ем, весь день не сплю — устаю
Re: Oracle: TOAD и свой софт - разные планы запросов и скоро
От: e.slyusar  
Дата: 14.09.11 05:06
Оценка:
Здравствуйте, Neco, Вы писали:

В предложном коде, поменяйте местами вызовы:

sw.Start();
TestSystemDataNoParams();
sw.Stop();
double system_data_no_params = sw.Elapsed.TotalSeconds;

sw.Start();
TestSystemData();
sw.Stop();
double system_data = sw.Elapsed.TotalSeconds;

т.е. сперва вызовите функцию TestSystemDataNoParams а за ней TestSystemData и вы будет тогда удивлены результатами.

Вообще при работе с базами данных, в частности с oracle установка подключения считается тяжелой операцией.
Глубоко внутри, что в System.Data.OracleClient, что в Oracle.DataAccess.Client, реализован пул коннектов.
При вызове первой функции создается коннект, выполняется запрос и коннект возвращается в пулл НО НЕ УНИЧТОЖАЕТСЯ!!!
При вызове второй функции коннект поднимается из пула и время на установление соединения с БД не тратится.

З.Ы. Вот отсюда и в TOAD такое время выполнения, ихмо он ходит уже по готовому коннекту.
З.З.Ы. И вообще, если работаете с Oracle то используйте Oracle Data Provider for .NET (http://www.oracle.com/technetwork/topics/dotnet/index-085163.html)
а если поверх ODP.NET использовать BlToolKit

Извиняюсь за много кода

        using OracleConnection = Oracle.DataAccess.Client.OracleConnection;
        using OracleDataAdapter = Oracle.DataAccess.Client.OracleDataAdapter;

        static void Main(string[] args)
        {
            var sw = new System.Diagnostics.Stopwatch();

            using (var conn = CreateConnection(_сonStr2))
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select null from dual";
                    cmd.ExecuteNonQuery();
                }

                sw.Start();
                TestSystemDataNoParams(conn);
                sw.Stop();
                double system_data_no_params = sw.Elapsed.TotalSeconds;

                sw.Reset();

                sw.Start();
                TestSystemData(conn);
                sw.Stop();
                double system_data = sw.Elapsed.TotalSeconds;

                sw.Reset();

                sw.Start();
                TestBlToolKit(conn);
                sw.Stop();
                double blToolKit_data1 = sw.Elapsed.TotalSeconds;

                sw.Reset();

                sw.Start();
                TestBlToolKit(conn);
                sw.Stop();
                double blToolKit_data2 = sw.Elapsed.TotalSeconds;

                sw.Reset();

                sw.Start();
                TestBlToolKit(conn);
                sw.Stop();
                double blToolKit_data3 = sw.Elapsed.TotalSeconds;

                Console.WriteLine(string.Format("system.data {0}, system.data (no params) {1}, blToolKit {2}\\{3}\\{4}"
                                                , system_data, system_data_no_params, blToolKit_data1, blToolKit_data2,
                                                blToolKit_data3));
            }
        }

        private static OracleConnection CreateConnection(string conStr)
        {
            var conn = new OracleConnection(conStr);
            
            //Открываем коннект
            conn.Open();

            //принудительно инициализируем 
            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = "select null from dual";
                cmd.ExecuteNonQuery();
            }

            return conn;
        }

        private static void TestBlToolKit(OracleConnection conn)
        {
            using (var db = new DbManager(conn))
            {
                db.SetCommand("select * from glossary where type = :pType"
                              , db.Parameter("pType", 123))
                    .ExecuteDataTable();
            }
        }

        private static void TestSystemData(OracleConnection conn)
        {
                var sb = new StringBuilder();
                sb.AppendLine("select * from glossary where type = :pType");
                sb.AppendLine("order by 2 asc");

                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sb.ToString();
                    AddParam(cmd, "pType", DbType.Int32, 123);

                    using (var adap = new OracleDataAdapter(cmd))
                    {
                        var tbl = new DataTable();
                        adap.Fill(tbl);
                    }

                }
        }

        private static void TestSystemDataNoParams(OracleConnection conn)
        {
                var sb = new StringBuilder();
                sb.AppendLine("select * from glossary where type = 123");
                sb.AppendLine("order by 2 asc");

                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sb.ToString();

                    using (var adap = new OracleDataAdapter(cmd))
                    {
                        var tbl = new DataTable();
                        adap.Fill(tbl);
                    }

                }
        }

        private static void AddParam(IDbCommand cmd, string name, DbType type, object value)
        {
            IDbDataParameter rez = cmd.CreateParameter();
            rez.ParameterName = name;
            rez.DbType = type;
            rez.Value = value;
            cmd.Parameters.Add(rez);
        }
Re[2]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 14.09.11 06:44
Оценка:
Здравствуйте, e.slyusar, Вы писали:

ES>В предложном коде, поменяйте местами вызовы:

Спасибо за ответ, но более 150 секунд это слишком уж много для открытия соединения. ))

тем более я это всё заметил на продакшн коде, где пулы конечно используются.

но объективности ради, я конечно поменял местами, как Вы просили.
вот код:
            var sw = new System.Diagnostics.Stopwatch();

            sw.Reset();
            sw.Start();
            TestSystemDataNoParams();
            sw.Stop();
            double system_data_no_params = sw.Elapsed.TotalSeconds;

            sw.Reset();
            sw.Start();
            TestSystemData();
            sw.Stop();
            double system_data = sw.Elapsed.TotalSeconds;

            sw.Reset();
            sw.Start();
            TestOdbc();
            sw.Stop();
            double odbc = sw.Elapsed.TotalSeconds;

вот результат:
system.data 170.6726251, system.data (no params) 9.7868333, odbc 16.0092746
т.е. ничего принципиально не поменялось.

ES>З.З.Ы. И вообще, если работаете с Oracle то используйте Oracle Data Provider for .NET (http://www.oracle.com/technetwork/topics/dotnet/index-085163.html)

как я писал в оригинальном сообщении — я тоже думал, что ODP.Net исправит ситуацию, но, к сожалению, не помогло. Он также долго думает, а по завершении этого долгого времени ещё и выдавал ошибку invalid number на одном из рабочих запросов.
вот счас добавил к тесту odp:
system.data 158.0326224, system.data (no params) 0.8253322, odbc 2.9505964, odp 165.9107353, odp no params 5.1539829

в порядке бреда запускал релиз-версии — безрезультатно.
system.data 170.0237713, system.data (no params) 1.2875285, odbc 3.4835377, odp 162.6703569, odp no params 1.2028065

ES>Извиняюсь за много кода

это ничего, спасибо ))

что меня убивает в этой ситуации, так это что наверняка ODBC использует нативную оракловую библиотеку — вопрос только "как он её использует?"...
всю ночь не ем, весь день не сплю — устаю
Re[2]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: fddima  
Дата: 14.09.11 08:13
Оценка:
Здравствуйте, Neco, Вы писали:

N>если заменить все переменные на константы — то запрос также выполняется очень быстро. так что тесты с sqlplus и экселем можно считать несостоявшимися — я не знаю как там переменные всавлять в запрос, поэтому сразу писал с константами.

В базе для строк используется VARCHAR?
DbType.String — это NVARCHAR. Как с этим в Оракле — я не знаю, но в MSSQL в некоторых случаях делает CAST внутри предиката, поэтому если параметры не соответствуют -> получаем жуткую деградацию.
Re: Oracle: TOAD и свой софт - разные планы запросов и скоро
От: e.slyusar  
Дата: 14.09.11 09:12
Оценка:
А какая у вас версия ODAC.NET? И какая версия СУБД?

в моем случае, тормозов с переменными нет (естественно на другой схеме данных)
Re[3]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 14.09.11 09:39
Оценка:
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, Neco, Вы писали:


N>>если заменить все переменные на константы — то запрос также выполняется очень быстро. так что тесты с sqlplus и экселем можно считать несостоявшимися — я не знаю как там переменные всавлять в запрос, поэтому сразу писал с константами.

F> В базе для строк используется VARCHAR?
F> DbType.String — это NVARCHAR. Как с этим в Оракле — я не знаю, но в MSSQL в некоторых случаях делает CAST внутри предиката, поэтому если параметры не соответствуют -> получаем жуткую деградацию.
спасибо за версию — для верности просто убрал использование параметров строкового типа. а также попробовал запускать запрос с каждым из параметров по очереди (а остальные два оставлять константами). картина та же.
всю ночь не ем, весь день не сплю — устаю
Re[2]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 14.09.11 09:52
Оценка:
Здравствуйте, e.slyusar, Вы писали:

ES>А какая у вас версия ODAC.NET? И какая версия СУБД?

ODAC112021Xcopy_32bit
СУБД 10.2.0.5.0

ES>в моем случае, тормозов с переменными нет (естественно на другой схеме данных)

на простых запросах этого тоже не наблюдается.
и даже больше.
внутри потрохов запроса используется вьюшка, которая смотрит на синоним из другой схемы. если я эту вьюшку заменяю эквивалентной таблицей, то всё ускоряется (что ожидаемо). а ещё такой нюанс вспомнился: в тоаде первоначально этот запрос тоже тормозил (правда не уверен что всё было настолько плохо — насколько помнится секунд двадцать висел) и чтобы соптимизировать его я хотел построить план запроса, на что получил ошибку типа "нет прав на нижележащие объекты". тогда я попросил dba дать нужные права на таблицы из зависимой схемы. они дали и запрос сразу стал выполняться быстрее.
т.е. я так понял, что у когда у аккаунта нет прав на статистику связанной схемы, то он может построить менее качественный план. с одной стороны бредово (движку-то СУБД должна быть доступна вся статистика, зачем идти от имени аккаунта...), ну да ладно — примем за данность.

но теперь-то я иду от аккаунта, у которого есть права. приложение и тоад работают из-под одного аккаунта.
всю ночь не ем, весь день не сплю — устаю
Re: Oracle: TOAD и свой софт - разные планы запросов и скоро
От: Neco  
Дата: 14.09.11 10:55
Оценка: -1
дополнил код, чтобы увидеть планы выполнения.
что-то типа
        private string GetPlan(IDbConnection conn, IDbDataAdapter adap) {
            var sb = new StringBuilder();
            sb.AppendLine("select ");
            sb.AppendLine("  substr (lpad(' ', level-1) || operation || ' (' || options || ')',1,30 ) \"Operation\", ");
            sb.AppendLine("  object_name                                                              \"Object\"");
            sb.AppendLine("from ");
            sb.AppendLine("  plan_table ");
            sb.AppendLine("start with id = 0 ");
            sb.AppendLine("connect by prior id=parent_id");

            using (var cmd = conn.CreateCommand()) {
                cmd.CommandText = sb.ToString();
                adap.SelectCommand = cmd;

                var ds = new DataSet();
                adap.Fill(ds);

                var rez_sb = new StringBuilder();
                foreach (DataRow one_row in ds.Tables[0].Rows) {
                    if (rez_sb.Length > 0) {
                        rez_sb.Append(Environment.NewLine);
                    }
                    foreach (var one_cell in one_row.ItemArray) {
                        rez_sb.Append(Convert.ToString(one_cell));
                        rez_sb.Append(";");
                    }
                }
                return rez_sb.ToString();
            }
        }


что интересно сравнил два дотнетовских варианта (с параметрами и без) — планы один-в-один.
with params:

SELECT STATEMENT (REMOTE);;
 PX COORDINATOR ();;
  PX SEND (QC (ORDER));:TQ10014;
   SORT (ORDER BY);;
    PX RECEIVE ();;
     PX SEND (RANGE);:TQ10013;
      HASH JOIN (BUFFERED);;
       PX RECEIVE ();;
        PX SEND (HASH);:TQ10011;
         VIEW ();VW_NSO_2;
          HASH (UNIQUE);;
           PX RECEIVE ();;
            PX SEND (HASH);:TQ10009;
             BUFFER (SORT);;
              NESTED LOOPS (OU;;
               NESTED LOOPS (O;;
                NESTED LOOPS (;;
                 NESTED LOOPS ;;
                  NESTED LOOPS;;
                   NESTED LOOP;;
                    NESTED LOO;;
                     NESTED LO;;
                      NESTED L;;
                       NESTED ;;
                        NESTED;;
                         HASH ;;
                          BUFF;;
                           PX ;;
                            PX;:TQ10002;
                             T;SB_SNAP;
                          PX R;;
                           PX ;:TQ10007;
                            HA;;
                             P;;
                              ;:TQ10005;
                              ;;
                              ;COST_CENTER_MASTER;
                             B;;
                              ;;
                              ;:TQ10001;
                              ;;
                              ;CONST;
                              ;PK_CONST;
                              ;PEOPLE_MASTER_SNAP;
                         INDEX;PK_STATUS;
                        TABLE ;SB_ACTION;
                         INDEX;PK_SB_ACTION;
                       TABLE A;SB_ACTION;
                        INDEX ;PK_SB_ACTION;
                      TABLE AC;PEOPLE_MASTER_SNAP;
                       INDEX (;PK_PEOPLE_MASTER_SNAP;
                     TABLE ACC;PEOPLE_MASTER_SNAP;
                      INDEX (U;PK_PEOPLE_MASTER_SNAP;
                    TABLE ACCE;PEOPLE_MASTER_SNAP;
                     INDEX (UN;PK_PEOPLE_MASTER_SNAP;
                   TABLE ACCES;PEOPLE_MASTER_SNAP;
                    INDEX (UNI;PK_PEOPLE_MASTER_SNAP;
                  TABLE ACCESS;PEOPLE_MASTER_SNAP;
                   INDEX (UNIQ;PK_PEOPLE_MASTER_SNAP;
                 TABLE ACCESS ;PEOPLE_MASTER_SNAP;
                  INDEX (UNIQU;PK_PEOPLE_MASTER_SNAP;
                VIEW PUSHED PR;V_PEOPLE_MASTER;
                 NESTED LOOPS ;;
                  NESTED LOOPS;;
                   NESTED LOOP;;
                    NESTED LOO;;
                     NESTED LO;;
                      NESTED L;;
                       NESTED ;;
                        TABLE ;PEOPLE_MASTER_SNAP;
                         INDEX;PK_PEOPLE_MASTER_SNAP;
                        TABLE ;PEOPLE_MASTER_SNAP;
                         INDEX;PK_PEOPLE_MASTER_SNAP;
                       TABLE A;COST_CENTER_MASTER;
                        INDEX ;PK_COST_CENTER_MASTER;
                      TABLE AC;PEOPLE_MASTER_SNAP;
                       INDEX (;PK_PEOPLE_MASTER_SNAP;
                     TABLE ACC;PEOPLE_MASTER_SNAP;
                      INDEX (U;PK_PEOPLE_MASTER_SNAP;
                    TABLE ACCE;PEOPLE_MASTER_SNAP;
                     INDEX (UN;PK_PEOPLE_MASTER_SNAP;
                   TABLE ACCES;PEOPLE_MASTER_SNAP;
                    INDEX (UNI;PK_PEOPLE_MASTER_SNAP;
                  TABLE ACCESS;PEOPLE_MASTER_SNAP;
                   INDEX (UNIQ;PK_PEOPLE_MASTER_SNAP;
               VIEW PUSHED PRE;V_PEOPLE_MASTER;
                NESTED LOOPS (;;
                 NESTED LOOPS ;;
                  NESTED LOOPS;;
                   NESTED LOOP;;
                    NESTED LOO;;
                     NESTED LO;;
                      NESTED L;;
                       TABLE A;PEOPLE_MASTER_SNAP;
                        INDEX ;PK_PEOPLE_MASTER_SNAP;
                       TABLE A;PEOPLE_MASTER_SNAP;
                        INDEX ;PK_PEOPLE_MASTER_SNAP;
                      TABLE AC;COST_CENTER_MASTER;
                       INDEX (;PK_COST_CENTER_MASTER;
                     TABLE ACC;PEOPLE_MASTER_SNAP;
                      INDEX (U;PK_PEOPLE_MASTER_SNAP;
                    TABLE ACCE;PEOPLE_MASTER_SNAP;
                     INDEX (UN;PK_PEOPLE_MASTER_SNAP;
                   TABLE ACCES;PEOPLE_MASTER_SNAP;
                    INDEX (UNI;PK_PEOPLE_MASTER_SNAP;
                  TABLE ACCESS;PEOPLE_MASTER_SNAP;
                   INDEX (UNIQ;PK_PEOPLE_MASTER_SNAP;
                 TABLE ACCESS ;PEOPLE_MASTER_SNAP;
                  INDEX (UNIQU;PK_PEOPLE_MASTER_SNAP;
       PX RECEIVE ();;
        PX SEND (HASH);:TQ10012;
         NESTED LOOPS ();;
          BUFFER (SORT);;
           PX RECEIVE ();;
            PX SEND (BROADCAST;:TQ10010;
             VIEW ();VW_NSO_1;
              HASH (UNIQUE);;
               PX RECEIVE ();;
                PX SEND (HASH);:TQ10008;
                 VIEW ();V_COST_CENTER_OWNERS;
                  SORT (UNIQUE;;
                   PX RECEIVE ;;
                    PX SEND (H;:TQ10006;
                     BUFFER (S;;
                      UNION-AL;;
                       FILTER ;;
                        HASH J;;
                         BUFFE;;
                          PX R;;
                           PX ;:TQ10000;
                            VI;;
                             N;;
                              ;PK_DOA_COST_CENTER;
                              ;DOA;
                              ;PK_DOA;
                         VIEW ;;
                          SORT;;
                           PX ;;
                            PX;:TQ10003;
                             U;;
                              ;;
                              ;COST_CENTER_MASTER;
                              ;;
                              ;COST_CENTER_MASTER;
                       FILTER ;;
                        VIEW (;;
                         SORT ;;
                          PX R;;
                           PX ;:TQ10004;
                            UN;;
                             F;;
                              ;;
                              ;COST_CENTER_MASTER;
                             F;;
                              ;;
                              ;COST_CENTER_MASTER;
          PX BLOCK (ITERATOR);;
           TABLE ACCESS (FULL);COST_CENTER_MASTER;
            TABLE ACCESS (BY I;CONST;
             INDEX (UNIQUE SCA;PK_CONST;


а вот из-под тоада отличается
Toad:

SELECT STATEMENT ()    {null}
 TEMP TABLE TRANSFORMATION ()    {null}
  PX COORDINATOR ()    {null}
   PX SEND (QC (RANDOM))    :TQ10002
    LOAD AS SELECT ()    COST_CENTER_MASTER
     PX RECEIVE ()    {null}
      PX SEND (ROUND-ROBIN)    :TQ10001
       VIEW ()    {null}
        SORT (UNIQUE)    {null}
         PX RECEIVE ()    {null}
          PX SEND (HASH)    :TQ10000
           UNION-ALL ()    {null}
            PX BLOCK (ITERATOR    {null}
             TABLE ACCESS (FUL    COST_CENTER_MASTER
            PX BLOCK (ITERATOR    {null}
             TABLE ACCESS (FUL    COST_CENTER_MASTER
  PX COORDINATOR ()    {null}
   PX SEND (QC (ORDER))    :TQ20012
    SORT (ORDER BY)    {null}
     PX RECEIVE ()    {null}
      PX SEND (RANGE)    :TQ20011
       HASH JOIN (BUFFERED)    {null}
        PX RECEIVE ()    {null}
         PX SEND (HASH)    :TQ20009
          VIEW ()    VW_NSO_2
           HASH (UNIQUE)    {null}
            PX RECEIVE ()    {null}
             PX SEND (HASH)    :TQ20007
              BUFFER (SORT)    {null}
               NESTED LOOPS (O    {null}
                NESTED LOOPS (    {null}
                 NESTED LOOPS     {null}
                  NESTED LOOPS    {null}
                   NESTED LOOP    {null}
                    NESTED LOO    {null}
                     NESTED LO    {null}
                      NESTED L    {null}
                       NESTED     {null}
                        NESTED    {null}
                         NESTE    {null}
                          HASH    {null}
                           BUF    {null}
                            PX    {null}
                             P    :TQ20002
                                  SB_SNAP
                           PX     {null}
                            PX    :TQ20005
                             H    {null}
                                  {null}
                                  :TQ20003
                                  {null}
                                  COST_CENTER_MASTER
                                  {null}
                                  {null}
                                  :TQ20001
                                  {null}
                                  CONST
                                  PK_CONST
                                  PEOPLE_MASTER_SNAP
                          INDE    PK_STATUS
                         TABLE    SB_ACTION
                          INDE    PK_SB_ACTION
                        TABLE     SB_ACTION
                         INDEX    PK_SB_ACTION
                       TABLE A    PEOPLE_MASTER_SNAP
                        INDEX     PK_PEOPLE_MASTER_SNAP
                      TABLE AC    PEOPLE_MASTER_SNAP
                       INDEX (    PK_PEOPLE_MASTER_SNAP
                     TABLE ACC    PEOPLE_MASTER_SNAP
                      INDEX (U    PK_PEOPLE_MASTER_SNAP
                    TABLE ACCE    PEOPLE_MASTER_SNAP
                     INDEX (UN    PK_PEOPLE_MASTER_SNAP
                   TABLE ACCES    PEOPLE_MASTER_SNAP
                    INDEX (UNI    PK_PEOPLE_MASTER_SNAP
                  TABLE ACCESS    PEOPLE_MASTER_SNAP
                   INDEX (UNIQ    PK_PEOPLE_MASTER_SNAP
                 VIEW PUSHED P    V_PEOPLE_MASTER
                  NESTED LOOPS    {null}
                   NESTED LOOP    {null}
                    NESTED LOO    {null}
                     NESTED LO    {null}
                      NESTED L    {null}
                       NESTED     {null}
                        NESTED    {null}
                         TABLE    PEOPLE_MASTER_SNAP
                          INDE    PK_PEOPLE_MASTER_SNAP
                         TABLE    PEOPLE_MASTER_SNAP
                          INDE    PK_PEOPLE_MASTER_SNAP
                        TABLE     COST_CENTER_MASTER
                         INDEX    PK_COST_CENTER_MASTER
                       TABLE A    PEOPLE_MASTER_SNAP
                        INDEX     PK_PEOPLE_MASTER_SNAP
                      TABLE AC    PEOPLE_MASTER_SNAP
                       INDEX (    PK_PEOPLE_MASTER_SNAP
                     TABLE ACC    PEOPLE_MASTER_SNAP
                      INDEX (U    PK_PEOPLE_MASTER_SNAP
                    TABLE ACCE    PEOPLE_MASTER_SNAP
                     INDEX (UN    PK_PEOPLE_MASTER_SNAP
                   TABLE ACCES    PEOPLE_MASTER_SNAP
                    INDEX (UNI    PK_PEOPLE_MASTER_SNAP
                VIEW PUSHED PR    V_PEOPLE_MASTER
                 NESTED LOOPS     {null}
                  NESTED LOOPS    {null}
                   NESTED LOOP    {null}
                    NESTED LOO    {null}
                     NESTED LO    {null}
                      NESTED L    {null}
                       NESTED     {null}
                        TABLE     PEOPLE_MASTER_SNAP
                         INDEX    PK_PEOPLE_MASTER_SNAP
                        TABLE     PEOPLE_MASTER_SNAP
                         INDEX    PK_PEOPLE_MASTER_SNAP
                       TABLE A    COST_CENTER_MASTER
                        INDEX     PK_COST_CENTER_MASTER
                      TABLE AC    PEOPLE_MASTER_SNAP
                       INDEX (    PK_PEOPLE_MASTER_SNAP
                     TABLE ACC    PEOPLE_MASTER_SNAP
                      INDEX (U    PK_PEOPLE_MASTER_SNAP
                    TABLE ACCE    PEOPLE_MASTER_SNAP
                     INDEX (UN    PK_PEOPLE_MASTER_SNAP
                   TABLE ACCES    PEOPLE_MASTER_SNAP
                    INDEX (UNI    PK_PEOPLE_MASTER_SNAP
                  TABLE ACCESS    PEOPLE_MASTER_SNAP
                   INDEX (UNIQ    PK_PEOPLE_MASTER_SNAP
        PX RECEIVE ()    {null}
         PX SEND (HASH)    :TQ20010
          NESTED LOOPS ()    {null}
           BUFFER (SORT)    {null}
            PX RECEIVE ()    {null}
             PX SEND (BROADCAS    :TQ20008
              VIEW ()    VW_NSO_1
               HASH (UNIQUE)    {null}
                PX RECEIVE ()    {null}
                 PX SEND (HASH    :TQ20006
                  VIEW ()    V_COST_CENTER_OWNERS
                   SORT (UNIQU    {null}
                    PX RECEIVE    {null}
                     PX SEND (    :TQ20004
                      UNION-AL    {null}
                       FILTER     {null}
                        HASH J    {null}
                         BUFFE    {null}
                          PX R    {null}
                           PX     :TQ20000
                            VI    {null}
                             N    {null}
                                  PK_DOA_COST_CENTER
                                  DOA
                                  PK_DOA
                         VIEW     {null}
                          PX B    {null}
                           TAB    SYS_TEMP_0FD9D6EFB_216989B7
                       FILTER     {null}
                        VIEW (    {null}
                         PX BL    {null}
                          TABL    SYS_TEMP_0FD9D6EFB_216989B7
           PX BLOCK (ITERATOR)    {null}
            TABLE ACCESS (FULL    COST_CENTER_MASTER
             TABLE ACCESS (BY     CONST
              INDEX (UNIQUE SC    PK_CONST


выделенной жирным части в варианте с дотнетом нет. остальное выглядит похоже.
всю ночь не ем, весь день не сплю — устаю
Re[3]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Аноним  
Дата: 14.09.11 12:47
Оценка:
N> sb.AppendLine(" where (nvl(id, (select value from const where id_key='cc_for_orphans')) in (");
N> sb.AppendLine(" select cco.cost_center");
N> sb.AppendLine(" from v_cost_center_owners cco");
N> sb.AppendLine(" where cco.actual_owner_badge = :approver_badge");
N> sb.AppendLine(" and nvl(cco.doa_case_id_key,'-') <> :self_doa_partial

Так верстают только сами знаете кто. nvl(field) = :var — это нет. nvl(id) = — это совсем нет.
Напиши запрос нормально и всё само пройдёт (имхо).
Re[2]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Аноним  
Дата: 14.09.11 12:55
Оценка:
N> NESTED LOOPS (OU;;
N> NESTED LOOPS (O;;
N> NESTED LOOPS (;;
N> NESTED LOOPS ;;
N> NESTED LOOPS;;
N> NESTED LOOP;;
N> NESTED LOO;;
N> NESTED LO;;
N> NESTED L;;
N> NESTED ;;
N> NESTED;;
N> HASH ;;
N> BUFF;;
N> PX ;;

По твоему план должен так выглядеть? Не кажется тебе странным этот набор строк?
Re[4]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 14.09.11 12:57
Оценка:
Здравствуйте, Аноним, Вы писали:

N>> sb.AppendLine(" where (nvl(id, (select value from const where id_key='cc_for_orphans')) in (");

N>> sb.AppendLine(" select cco.cost_center");
N>> sb.AppendLine(" from v_cost_center_owners cco");
N>> sb.AppendLine(" where cco.actual_owner_badge = :approver_badge");
N>> sb.AppendLine(" and nvl(cco.doa_case_id_key,'-') <> :self_doa_partial
А>Так верстают только сами знаете кто.
— кто же ходит за мёдом с воздушным шаром?
— я хожу

А>nvl(field) = :var — это нет. nvl(id) = — это совсем нет.

А>Напиши запрос нормально и всё само пройдёт (имхо).
ну тоад считает, что запрос написан нормально.
собственно суть моего вопроса не в том, как ускорить выполение запроса, а почему поведение разное из-под тоада и из под кода.
всю ночь не ем, весь день не сплю — устаю
Re[3]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 14.09.11 13:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>По твоему план должен так выглядеть? Не кажется тебе странным этот набор строк?

мне кажутся странными только твои комментарии
всю ночь не ем, весь день не сплю — устаю
Re[4]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Аноним  
Дата: 14.09.11 13:38
Оценка:
Здравствуйте, Neco, Вы писали:

N>Здравствуйте, Аноним, Вы писали:


А>>По твоему план должен так выглядеть? Не кажется тебе странным этот набор строк?

N>мне кажутся странными только твои комментарии

Поясню. Ты выдал в аутпут текстовый мусор. Сообщив, что как видите планы совпадают. Это слегка настораживает.
Вот я и поинтересовался,что такое по твоему план запроса и как он должен выглядеть.
(я не знаю может ты в уме склеиваешь как надо строки и тебе всё понятно).
Re[5]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 14.09.11 16:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>По твоему план должен так выглядеть? Не кажется тебе странным этот набор строк?

N>>мне кажутся странными только твои комментарии
А>Поясню. Ты выдал в аутпут текстовый мусор. Сообщив, что как видите планы совпадают. Это слегка настораживает.
А>Вот я и поинтересовался,что такое по твоему план запроса и как он должен выглядеть.
А>(я не знаю может ты в уме склеиваешь как надо строки и тебе всё понятно).
ок, какая именно информация из плана запроса нужна? или если есть под рукой готовый sql, который вытягивает инфу так, как надо — выложи сюда, я прогоню и покажу отчёт в том виде, каком тебе удобно.

просто я сам в дебрях планов запроса не разбираюсь. но два плана на идентичность сравнить могу (чисто по форме лесенки и началу строк).
всю ночь не ем, весь день не сплю — устаю
Re: Oracle: TOAD и свой софт - разные планы запросов и скоро
От: B0rG  
Дата: 15.09.11 11:01
Оценка:
Здравствуйте, Neco, Вы писали:


SELECT T.ID, T.NAME, T.IS_ACTIVE
FROM V_COST_CENTER_MASTER T 
WHERE 
(
    NVL(T.ID, (SELECT VALUE FROM CONST WHERE ID_KEY='CC_FOR_ORPHANS') ) /* 1 */
    IN (
       SELECT CCO.COST_CENTER FROM V_COST_CENTER_OWNERS CCO 
       WHERE CCO.ACTUAL_OWNER_BADGE = :APPROVER_BADGE 
       AND NVL(CCO.DOA_CASE_ID_KEY,'-') <> :SELF_DOA_PARTIAL /* 2 */
        )
) 
AND 
(
    ID IN ( SELECT ORG_COST_CENTER FROM V_SB_SNAP_FULL WHERE RENEWAL_ID= :RENEWAL_ID ) /* 3 */
)
ORDER BY T.ID ASC


Уважаемый, пишите запросы крупным почерком — берегите глаза чекистов.

дальше комментарии по запросу —
1. поменять на константу, потому как оно и будет константой, это уберет NVL и поможет оптимайзеру
2. переписать по человечески, хотя бы как where DOA_CASE_ID_KEY IS NOT NULL AND DOA_CASE_ID_KEY <> :SELF_DOA_PARTIAL
3. сделайте union на первую и вторую часть условия и по этому юниону уже select from cost_center_master where id in ( select a.id union all select b.id).

так же поможет следующая инфа
DESCRIBE V_COST_CENTER_MASTER; 
DESCRIBE V_COST_CENTER_OWNERS; 
DESCRIBE V_SB_SNAP_FULL;
Re[2]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: Neco  
Дата: 15.09.11 12:18
Оценка:
Здравствуйте, B0rG, Вы писали:

BG>Уважаемый, пишите запросы крупным почерком — берегите глаза чекистов.

переписал вот так:
SELECT T.ID, T.NAME, T.IS_ACTIVE
FROM V_COST_CENTER_MASTER T 
WHERE 
(
    T.ID
    IN (
       SELECT TO_CHAR(NVL(CCO.COST_CENTER,:DEFAULT_CC))
       FROM V_COST_CENTER_OWNERS CCO 
       WHERE CCO.ACTUAL_OWNER_BADGE = :APPROVER_BADGE 
       AND (CCO.DOA_CASE_ID_KEY IS NULL OR CCO.DOA_CASE_ID_KEY <> :SELF_DOA_PARTIAL)
       INTERSECT
       SELECT ORG_COST_CENTER FROM V_SB_SNAP_FULL WHERE RENEWAL_ID= :RENEWAL_ID
        )
) 
ORDER BY T.ID ASC


BG>дальше комментарии по запросу —

BG>1. поменять на константу, потому как оно и будет константой, это уберет NVL и поможет оптимайзеру
заменил переменной. в приниципе да — могу вычислять это перед запросом (лишний поход в базу, ну да фиг с ним).

BG>2. переписать по человечески, хотя бы как where DOA_CASE_ID_KEY IS NOT NULL AND DOA_CASE_ID_KEY <> :SELF_DOA_PARTIAL

это меняет суть запроса. с AND там не получается — надо брать либо когда слева null, либо когда значения равны.

BG>3. сделайте union на первую и вторую часть условия и по этому юниону уже select from cost_center_master where id in ( select a.id union all select b.id).

это тоже меняет суть запроса. тогда выбираются и те и другие, а надо тех, которые и там и там. заменил на intersect.

BG>так же поможет следующая инфа


VIEW v_cost_center_master
 Name                                      Null?    Type                        
 ----------------------------------------- -------- ----------------------------
 ID                                                 NVARCHAR2                   
 NAME                                               VARCHAR2(90)                
 IS_ACTIVE                                          NUMBER                      
 CC_OWNER1_BADGE                                    NUMBER(8)                   
 CC_OWNER1_NAME                                     VARCHAR2(40)                
 CC_OWNER2_BADGE                                    NUMBER(8)                   
 CC_OWNER2_NAME                                     VARCHAR2(40)                

VIEW v_cost_center_owners
 Name                                      Null?    Type                        
 ----------------------------------------- -------- ----------------------------
 COST_CENTER                                        NVARCHAR2                   
 RL_OWNER_BADGE                                     NUMBER(8)                   
 ACTUAL_OWNER_BADGE                                 NUMBER                      
 DUE_TO_DELEGATION                                  NUMBER                      
 DOA_CASE_ID_KEY                                    NVARCHAR2                   
 DIRECT                                             NUMBER                      

VIEW v_sb_snap_full
 Name                                      Null?    Type                        
 ----------------------------------------- -------- ----------------------------
 ID                                        NOT NULL NUMBER                      
 RENEWAL_ID                                NOT NULL NUMBER                      
 EMP_BADGE                                 NOT NULL NUMBER                      
 ORG_COST_CENTER_SNAP                      NOT NULL NVARCHAR2                   
 STATUS_ID_KEY                             NOT NULL NVARCHAR2                   
 STATUS_NAME                                        NVARCHAR2                   
 CONFIRM_ACTION_ID                                  NUMBER                      
 CONFIRM_ACTION_COMMENT                             NVARCHAR2                   
 CONFIRMATION_DATE                                  DATE                        
 CONFIRMER_BADGE                                    NUMBER                      
 CONFIRMER_NAME                                     VARCHAR2(136)               
 APPROVE_ACTION_ID                                  NUMBER                      
 APPROVE_ACTION_COMMENT                             NVARCHAR2                   
 APPROVAL_DATE                                      DATE                        
 APPROVER_BADGE                                     NUMBER                      
 APPROVER_NAME                                      VARCHAR2(136)               
 EMP_NAME                                           VARCHAR2(136)               
 EMP_SEARCH_TYPE                                    VARCHAR2(9)                 
 EMP_TYPE                                           VARCHAR2(9)                 
 EMP_USER_ID                                        VARCHAR2(255)               
 EMP_COST_CENTER                                    VARCHAR2(36)                
 EMP_COST_CENTER_NAME                               VARCHAR2(90)                
 ORG_COST_CENTER                                    VARCHAR2(1500)              
 EMP_HOME_COMPANY_NAME                              VARCHAR2(120)               
 LINE_SUP1_AB_NUMBER                                NUMBER(8)                   
 LINE_SUP1_NORM_ENG_FULL_NAME                       VARCHAR2(136)               
 LINE_SUP2_AB_NUMBER                                NUMBER(8)                   
 LINE_SUP2_NORM_ENG_FULL_NAME                       VARCHAR2(136)


немного поясню вопрос:
1. код SQL генерируется. причём различные участки повторно используются, что собственно и делает генерацию нужной — замена статическим оптимизированным SQL-выражением приведёт к многочисленным копи-пастам, чего не хотелось бы.
2. у меня уже есть workaround — если я делаю вьюшку материализованными представлениями, то всё начинает летать как в тоаде, так и в софте. вьюшки обновляются раз в сутки ночью — можно себе это позволить. другой workaround — внутри одной из вьюшек добавить хинт NO_USE_HASH. тогда запрос начинает выполняться за 6 секунд в обоих случаях (toad vs .net).
3. вопрос не в том, как улучшить SQL-запрос или вьюшки, а в том, как добиться одинакового поведения и узнать почему оно собственно рознится. почему принимая запрос из toad'а оракл выполняет TEMP TABLE TRANSFORMATION, а принимая тот же запрос из дотнета, почему-то не хочет.
всю ночь не ем, весь день не сплю — устаю
Re[2]: Oracle: TOAD и свой софт - разные планы запросов и ск
От: rumatavz  
Дата: 15.09.11 13:45
Оценка:
Попробуйте и там и там выполнить запрос с хинтами — ALL_ROWS, RULE, FIRST_ROWS
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.