Оптимизация Запроса Select, который отстает на Oracle, которая работает быстро на SQL Server

Я использую Jasob в течение многих лет, и это руки вниз лучший obfuscator там. Он имеет расширенный интерфейс, но по-прежнему интуитивно понятен и прост в использовании. Он также будет обрабатывать файлы HTML и CSS.

Лучший способ использовать это префикс для всех ваших private переменных чем-то вроде подчеркивания, а затем использовать функцию sort объединить их все вместе и проверить их как цели для обфускации.

Пользователи могут по-прежнему просматривать ваш источник, но гораздо сложнее расшифровать, когда ваши частные переменные преобразуются из чего-то вроде _sUserPreferredNickName в a.

Двигатель автоматически будет подсчитываться количество целевых переменных и приоритет их для получения максимального сжатия.

Я не работаю для Jasob, и я ничего не получаю от их продвижения, просто предлагая дружеские советы. Недостатком является то, что он не является бесплатным и немного дорогим, но все же стоит того, чтобы укладываться в альтернативные варианты - «свободные» варианты даже не приближаются.

12
задан RickL 25 September 2008 в 15:22
поделиться

18 ответов

Часто этот тип проблемы уходит при анализе включенных таблиц (таким образом, Oracle имеет лучшую идею распределения данных),

ANALYZE TABLE tasks COMPUTE STATISTICS;
9
ответ дан 2 December 2019 в 19:56
поделиться

Подзапросы "плохи" с Oracle. Это обычно лучше, действительно используют соединения.

Вот статья о том, как переписать Ваши подзапросы с соединением: http://www.dba-oracle.com/sql/t_rewrite_subqueries_performance.htm

-2
ответ дан 2 December 2019 в 19:56
поделиться

Если у Вас нет индекса по столбцам Engineer1 и Engineer2 затем, Вы всегда собираетесь генерировать Сканирование таблицы в SQL Server и эквиваленте независимо от того, что это может быть в Oracle.

Если Вам просто нужны Заказы, которые освободили задачи затем, следующее должно работать просто великолепно на обеих платформах, но необходимо также полагать, что добавление индексов к таблице Tasks улучшает производительность запроса.

SELECT DISTINCT orderID 
FROM tasks 
WHERE (engineer1 IS NULL OR engineer2 IS NULL)
-1
ответ дан 2 December 2019 в 19:56
поделиться

Вот альтернативный подход, который я думаю, дает то, что Вы хотите:

SELECT orderID
 FROM tasks
 GROUP BY orderID
 HAVING COUNT(engineer1) = 0 OR COUNT(engineer2) = 0

Я не уверен, хотите ли Вы "И" или "ИЛИ" в пункте НАЛИЧИЯ. Это походит согласно бизнес-логике, эти два поля должны или оба быть заполнены или оба быть ПУСТЫМИ; если это гарантируется затем, Вы могли бы уменьшить условие до просто проверки engineer1.

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

-1
ответ дан 2 December 2019 в 19:56
поделиться

Я соглашаюсь с ΤΖΩΤΖΙΟΥ и wearejimbo, что Ваш запрос должен быть...

SELECT DISTINCT orderID FROM Tasks 
WHERE Engineer1 IS NULL OR Engineer2 IS NULL;

Я не знаю о SQL Server, но этот запрос не сможет использовать в своих интересах любые индексы, потому что пустые строки не находятся в индексах. Решение этого состояло бы в том, чтобы переписать запрос способом, который позволит основанному на функции индексу быть созданным, который только включает строки нулевого значения. Это могло быть сделано с NVL2, но вероятно не будет портативно к SQL Server.

Я думаю, что лучший ответ не является тем, который соответствует Вашим критериям, и это - запись другой оператор для каждой платформы, которая является лучшей для той платформы.

0
ответ дан 2 December 2019 в 19:56
поделиться

Новое взятие.

Эквивалентность:

  • КОЛИЧЕСТВО () функция не считает Нулевые значения

и

  • Вы хотите заказанные из всех задач, где ни одна из задач не имеет или engineer1 или набор engineer2 к значению

затем это должно сделать то, что Вы хотите:

SELECT orderID
FROM tasks
GROUP BY orderID
HAVING COUNT(engineer1) = 0 AND COUNT(engineer2) = 0

Протестируйте его.

0
ответ дан 2 December 2019 в 19:56
поделиться

Не Ваш запрос то же как

SELECT orderID FROM tasks
WHERE engineer1 IS NOT NULL OR engineer2 IS NOT NULL

?

0
ответ дан 2 December 2019 в 19:56
поделиться

Другая опция состоит в том, чтобы использовать МИНУС (ЗА ИСКЛЮЧЕНИЕМ MSSQL)

SELECT orderID FROM tasks
MINUS
SELECT DISTINCT orderID FROM tasks WHERE engineer1 IS NOT NULL 
AND engineer2 IS NOT NULL
0
ответ дан 2 December 2019 в 19:56
поделиться

Оптимизатор Oracle делает хорошее задание обработки операторов MINUS. Если Вы перепишете свое использование запроса МИНУС, то оно, вероятно, будет работать вполне быстро:

SELECT orderID FROM tasks
MINUS
SELECT DISTINCT orderID FROM tasks WHERE
 engineer1 IS NOT NULL AND engineer2 IS NOT NULL
0
ответ дан 2 December 2019 в 19:56
поделиться

То, какая пропорция строк в таблице удовлетворяют условию "engineer1, ЯВЛЯЕТСЯ NOT NULL, И engineer2 ЯВЛЯЕТСЯ NOT NULL"?

Это говорит Вам (примерно), могло ли стоить попытаться использовать индекс для получения связанного orderid's.

Другой способ записать запрос в Oracle, которая обработала бы неиндексируемые случаи очень хорошо, будет:

select distinct orderid
from
(
select orderid,
       max(case when engineer1 is null and engineer2 is null then 0 else 1)
          over (partition by orderid)
          as max_null_finder
from   tasks
)
where max_null_finder = 0
0
ответ дан 2 December 2019 в 19:56
поделиться

Если бы Вы решаете составить таблицу ORDERS, я добавил бы флаг ALLOCATED к ней и создал бы растровый индекс. Этот подход также вынуждает Вас изменить бизнес-логику для держания флага в курсе, но запросы будут молнией быстро. Это зависит от того, насколько очень важный запросы для приложения.

Относительно ответов, более простое лучше в этом случае. Забудьте подзапросы, соединения, отличные и группа bys, они не нужны вообще!

0
ответ дан 2 December 2019 в 19:56
поделиться

"Хотя мне все еще любопытно, почему я должен сделать это, и если/когда я должен был бы выполнить его снова?"

Статистические данные дают optimzer информацию Oracle на основе издержек, что она должна определить эффективность различных планов выполнения: например, количество rowsin таблица, средняя ширина строк, самых высоких и самых низких значений для каждого столбца, количества отличных значений кластеризирующийся фактор для каждого столбца индексов и т.д.

В маленькой базе данных можно просто установить задание, чтобы собирать статистику каждую ночь и оставлять ее в покое. На самом деле это - значение по умолчанию менее чем 10 г. Для больших реализаций обычно необходимо взвешивать устойчивость планов выполнения против способа, которым изменяются данные, который является хитрым балансом.

Oracle также имеет функцию, названную "динамическая выборка", которая привыкла к демонстрационным таблицам для определения соответствующей статистики во время выполнения. Это намного чаще используется с хранилищами данных, где издержки выборки перевешиваемого потенциальной производительностью увеличиваются для продолжительного запроса.

1
ответ дан 2 December 2019 в 19:56
поделиться

Я думаю, что несколько человек имеют в значительной степени правильный SQL, но пропускают соединение между внутренними и внешними запросами.
Попробуйте это:

SELECT t1.orderID 
FROM   tasks t1
WHERE  NOT EXISTS
       (SELECT 1 
        FROM   tasks t2 
        WHERE  t2.orderID   = t1.orderID
        AND    t2.engineer1 IS NOT NULL 
        AND    t2.engineer2 IS NOT NULL)
1
ответ дан 2 December 2019 в 19:56
поделиться

Некоторые вопросы:

  • Сколько строк находится там в задачах?
  • Какие индексы определяются на нем?
  • Таблица была недавно проанализирована?

Другой способ записать тот же запрос был бы:

select orderid from tasks
minus
select orderid from tasks
where engineer1 IS NOT NULL AND engineer2 IS NOT NULL

Однако я ожидал бы, что запрос включит таблицу "заказов":

select orderid from ORDERS
minus
select orderid from tasks
where engineer1 IS NOT NULL AND engineer2 IS NOT NULL

или

select orderid from ORDERS
where orderid not in
( select orderid from tasks
  where engineer1 IS NOT NULL AND engineer2 IS NOT NULL
)

или

select orderid from ORDERS
where not exists
( select null from tasks
  where tasks.orderid = orders.orderid
  and   engineer1 IS NOT NULL OR engineer2 IS NOT NULL
)
2
ответ дан 2 December 2019 в 19:56
поделиться

Я соглашаюсь с TZQTZIO, я не получаю Ваш запрос.

Если мы предполагаем, что запрос действительно имел смысл затем, Вы могли бы хотеть попытаться использовать, СУЩЕСТВУЕТ, как некоторые предполагают и избегают В. В Не всегда плохо и существуют вероятные случаи, какой мог показать, что он на самом деле работает лучше, чем СУЩЕСТВУЕТ.

Заголовок вопроса не очень полезен. Я мог настроить этот запрос в одной базе данных Oracle и заставить его отстать и заставить его работать быстро в другом. Существует много факторов, которые определяют, как база данных разрешает запрос, объектную статистику, статистику схемы SYS, и параметры, а также производительность сервера. Sqlserver по сравнению с Oracle не является проблемой здесь.

Для заинтересованных оптимизацией запросов и производительностью и хотят узнать больше, некоторые условия Google для поиска являются "оракулом дубового стола" и "оракулом jonathan lewis".

2
ответ дан 2 December 2019 в 19:56
поделиться

Я попытался бы использовать соединения вместо этого

SELECT 
    t.orderID 
FROM 
    tasks  t
    LEFT JOIN tasks t1
        ON t.orderID =  t1.orderID
        AND t1.engineer1 IS NOT NULL 
        AND t1.engineer2 IS NOT NULL
WHERE
    t1.orderID IS NULL 

также Ваш исходный запрос, вероятно, было бы легче понять, был ли он указан как:

SELECT orderID FROM orders WHERE orderID NOT IN 
(SELECT DISTINCT orderID FROM tasks WHERE
 engineer1 IS NOT NULL AND engineer2 IS NOT NULL)

(принятие Вас имеет таблицу заказов со всеми перечисленными заказами),

который может быть затем переписан с помощью соединений как:

SELECT 
    o.orderID 
FROM 
    orders o
    LEFT JOIN tasks t
        ON o.orderID =  t.orderID
        AND t.engineer1 IS NOT NULL 
        AND t.engineer2 IS NOT NULL
WHERE
    t.orderID IS NULL 
3
ответ дан 2 December 2019 в 19:56
поделиться

Как насчет:

SELECT DISTINCT orderID FROM tasks t1 WHERE NOT EXISTS (SELECT * FROM tasks t2 WHERE t2.orderID=t1.orderID AND (engineer1 IS NOT NULL OR engineer2 IS NOT NULL));

Я не гуру оптимизации, но возможно Вы также пропустили некоторые индексы в своей базе данных Oracle.

0
ответ дан 2 December 2019 в 19:56
поделиться

"В" - пункт, как известно, в Oracle является довольно медленным. На самом деле внутренний оптимизатор запросов в Oracle не может обработать операторы с "В" довольно хорошем. попытайтесь использовать, "СУЩЕСТВУЕТ":

SELECT orderID FROM tasks WHERE orderID NOT EXISTS 
    (SELECT DISTINCT orderID FROM tasks WHERE
         engineer1 IS NOT NULL AND engineer2 IS NOT NULL)`print("code sample");`

Внимание: Проверьте, создает ли запрос те же результаты данных.

Edith говорит: ooops, запрос не хорошо формируется, но общее представление корректно. Oracle должна выполнить полное сканирование таблицы на предмет второго (внутреннего) запроса, создать результаты и затем сравнить их с первым (внешним) запросом, вот почему она замедляется. Попробовать

SELECT orderID AS oid FROM tasks WHERE NOT EXISTS 
    (SELECT DISTINCT orderID AS oid2 FROM tasks WHERE
         engineer1 IS NOT NULL AND engineer2 IS NOT NULL and oid=oid2)

или что-то подобное ;-)

3
ответ дан 2 December 2019 в 19:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: