powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Выборка уникальных значений из хронологической таблицы
25 сообщений из 59, страница 1 из 3
Выборка уникальных значений из хронологической таблицы
    #33096075
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Иногда требуется сделать джойн по хитрому условию: для каждой записи ведущей таблицы выбрать только одну запись ведомой таблицы (обычно максимальную или минимальную) из всех, удовлетворяющих условиям соединения.

Как правило, это нужно для хронологических таблиц типа курсов валют: например, для каждой проводки необходимо выбрать эффективный курс на дату этой проводки.

Проблема в том, что обычный джойн с условием равенства тут не подходит: может не быть курса на каждый день, или он меняется чаще, чем раз в день.

Обычные джойны с группировкой и сортировкой работают медленно, и тут нам на помощь приходит хитрость. Блюстители чистоты SQL меня, конечно, засмеют, ну да мне не привыкать :)

Итак, дано:

Таблица проводок:
Код: plaintext
CREATE TABLE transactions (xid NUMBER, xsum FLOAT, xdate DATE, xcurrency NUMBER)

Таблица курсов:
Код: plaintext
CREATE TABLE rates (rcurrency NUMBER, rdate DATE, rrate FLOAT)

Итак, для начала создадим уникальный индекс:

Код: plaintext
CREATE UNIQUE INDEX ux_rate_currency_date ON rates (rcurrency, rdate)

Как правило, этот индекс и должен быть уникальным: два курса одной валюты на одну дату — это плохо.

Пишем запрос:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT	(
	SELECT	/*+ INDEX_DESC (r ux_rate_currency_date) */
		rrate
	FROM	rates r
	WHERE	r.rcurrency = x.xcurrency
		AND r.rdate <= x.xdate
		AND rownum =  1 
	) AS eff_rate
FROM	transactions x

Если мы посмотрим на план, то увидим там

ACCESS PATH: INDEX RANGE SCAN DESCENDING

, а также условие:

COUNT STOPKEY

Что это значит?

Это значит, что для каждой строки из ведущей таблицы (таблицы проводок) Oracle будет находить первую удовлетворяющую его запись путём сканирования по индексу, а затем останавливаться по условию rowcount = 1 и выкидывать результат в итоговый запрос в качестве поля eff_rate .

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

Если не будет найдено ни одной записи, то eff_rate примет значение NULL .

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

К сожалению, Oracle версии 9i не позволяет передавать в FIELD SUBQUERY поля из внешнего запроса, если глубина вложения FIELD SUBQUERY больше 1. То есть такой, казалось бы, естественный запрос:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
SELECT	(
	SELECT	rrate
	FROM	(
		SELECT	rate
		FROM	rates r
		WHERE	r.rcurrency = x.xcurrency
			AND r.rdate <= x.xdate
		ORDER BY
			r.rdate DESC
		)
	WHERE	rownum =  1 
FROM	transactions x

приведёт к ошибке ORA-00904: недопустимый идентификатор .

Поэтому и приходится использовать хинты для явного прописывания логики запроса.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33096432
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квасной
Код: plaintext
1.
2.
3.
4.
	SELECT	/*+ INDEX_DESC (r ux_rate_currency_date) */ 
        ...
	WHERE	...
		AND rownum =  1 
Это тысячи раз обсуждалось. И хотя существуют странные альтернативные мнения, но так делать категорически нельзя . Ибо порядок строк гарантирует ORDER BY и только ORDER BY.
Надёжней и понятней будет использовать функцию GetRate(x.xcurrency,x.xdate).
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33096508
Splain
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В 9-ке

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT	rrate
	FROM	(
		SELECT	rate
		FROM	rates r
		WHERE	r.rcurrency = x.xcurrency
			AND r.rdate <= x.xdate
		ORDER BY
			r.rdate DESC
		)
	WHERE	rownum =  1 


можно заменить на

Код: plaintext
1.
2.
3.
4.
SELECT MAX(rrate) KEEP (DENSE_RANK LAST ORDER BY r.rdate)
  FROM rates r
WHERE	r.rcurrency = x.xcurrency
      AND r.rdate <= x.xdate

производительность протестировать было негде
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33096846
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Elic Квасной
Код: plaintext
1.
2.
3.
4.
	SELECT	/*+ INDEX_DESC (r ux_rate_currency_date) */ 
        ...
	WHERE	...
		AND rownum =  1 
Это тысячи раз обсуждалось. И хотя существуют странные альтернативные мнения, но так делать категорически нельзя . Ибо порядок строк гарантирует ORDER BY и только ORDER BY.
Надёжней и понятней будет использовать функцию GetRate(x.xcurrency,x.xdate).

Дело в том, что сам факт вызова функции в Oracle сопряжён с довольно большими накладными расходами.

На тестовой базе в ведущей таблице около 2 000 000 строк, в ведомой — около 2 000. Мой запрос работает несколько секунд, а если использовать функцию, то время возрастает до десятков секунд — feel the difference :)

Что же до порядка строк — так он при корректном прописывании пути доступа по индексу тоже гарантирован.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33097079
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КваснойНа тестовой базе в ведущей таблице около 2 000 000 строк, в ведомой — около 2 000. Мой запрос работает несколько секунд, а если использовать функцию, то время возрастает до десятков секунд — feel the difference :)И что, эти два лимона каждый раз обсчитываются?
КваснойЧто же до порядка строк — так он при корректном прописывании пути доступа по индексу тоже гарантирован. Не гарантирован
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33097737
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SplainВ 9-ке

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT	rrate
	FROM	(
		SELECT	rate
		FROM	rates r
		WHERE	r.rcurrency = x.xcurrency
			AND r.rdate <= x.xdate
		ORDER BY
			r.rdate DESC
		)
	WHERE	rownum =  1 


можно заменить на

Код: plaintext
1.
2.
3.
4.
SELECT MAX(rrate) KEEP (DENSE_RANK LAST ORDER BY r.rdate)
  FROM rates r
WHERE	r.rcurrency = x.xcurrency
      AND r.rdate <= x.xdate

производительность протестировать было негде

К сожалению, в этом случае Oracle не использует INDEX RANGE SCAN DESCENDING с остановкой на первом значении.

Он делает INDEX RANGE SCAN по всем значениям, удовлетворяющим условию выборки, сортирует найденные строки по полю rdate ( SORT AGGREGATE ), и выбирает из них первую.

Производительность, соответственно, падает. Запрос работает несколько десятков секунд.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33097821
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Elic КваснойНа тестовой базе в ведущей таблице около 2 000 000 строк, в ведомой — около 2 000. Мой запрос работает несколько секунд, а если использовать функцию, то время возрастает до десятков секунд — feel the difference :)И что, эти два лимона каждый раз обсчитываются?

Ну, не каждый раз. Но даже с учётом фильтров лям строк нет-нет, да и получится.

КваснойЧто же до порядка строк — так он при корректном прописывании пути доступа по индексу тоже гарантирован. Не гарантирован

То, что наличие ORDER BY лучше, чем его отсутствие, объяснять никому не надо. Быть молодым, богатым, но здоровым гораздо лучше, чем бедным, старым, но больным.

В данном сообщении рассматривается следующий вопрос: «что делать, когда ORDER BY по каким-то причинам недоступен?»

Ответ на этот вопрос такой: «следует использовать хинт для доступа по индексу».
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098007
ы
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ы
Гость
КваснойВ данном сообщении рассматривается следующий вопрос: «что делать, когда ORDER BY по каким-то причинам недоступен?»
Или ликвидировать причину, или уволиться/застрелиться/повеситься/etc...

КваснойОтвет на этот вопрос такой: «следует использовать хинт для доступа по индексу».
Я за такие ответы бью "Oracle Database Error Messages" по голове. До наступления просветления. Другие кишки тупым ножом выпускают :)
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098026
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КваснойВ данном сообщении рассматривается следующий вопрос: «что делать, когда ORDER BY по каким-то причинам недоступен?»

Ответ на этот вопрос такой: «следует использовать хинт для доступа по индексу».Правильный результат достигается соответствующим образом сформулированным запросом. Хинты - это не способ формулирования запроса, это лишь способ достижения результата более эффективным методом.

Каждый волен рисковать по-своему. Я не собираюсь упорствовать в твоем разубеждении. Тебя научит жизнь.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098387
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ElicКаждый волен рисковать по-своему. Я не собираюсь упорствовать в твоем разубеждении. Тебя научит жизнь.

В общем, всё в лучших традициях религий мира: ссылки на мифическую «жизнь» вместо примеров того, когда предложенная конструкция не работает :)

На этот месте обычно следуют рассказы о том что случится, если индекс станет UNUSABLE . Мне до сих пор интересно: найдётся ли хоть один человек, который перед тем , как высказать такое опасение, сделает-таки индекс UNUSABLE и посмотрит, что произойдёт на самом деле? Ну просто из любопытства.

И ещё напомню: не человек для субботы, а суббота для человека . СУБД существуют не для того, чтобы программисты и администраторы писали в них красивые и правильные запросы, а для того, чтобы быстро возвращать заложенные в них данные.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098440
ы
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ы
Гость
КваснойВ общем, всё в лучших традициях религий мира: ссылки на мифическую «жизнь» вместо примеров того, когда предложенная конструкция не работает :)

На этот месте обычно следуют рассказы о том что случится, если индекс станет UNUSABLE . Мне до сих пор интересно: найдётся ли хоть один человек, который перед тем , как высказать такое опасение, сделает-таки индекс UNUSABLE и посмотрит, что произойдёт на самом деле? Ну просто из любопытства.

И ещё напомню: не человек для субботы, а суббота для человека . СУБД существуют не для того, чтобы программисты и администраторы писали в них красивые и правильные запросы, а для того, чтобы быстро возвращать заложенные в них данные.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
SQL*Plus: Release  9 . 2 . 0 . 6 . 0  - Production on Fri Jun  3   00 : 01 : 11   2005 

Copyright (c)  1982 ,  2002 , Oracle Corporation.  All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release  9 . 2 . 0 . 6 . 0  - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release  9 . 2 . 0 . 6 . 0  - Production

SQL> create table t as select * from all_objects;

Table created.

SQL> create unique index t_i on t(object_id,object_name);

Index created.

SQL> analyze table t compute statistics;

Table analyzed.

SQL> set autotrace traceonly exp
SQL> select object_name from t order by object_id ;

Execution Plan
----------------------------------------------------------
    0       SELECT STATEMENT Optimizer=CHOOSE (Cost= 78  Card= 27240  Bytes=
           735480 )

    1      0    INDEX (FULL SCAN) OF 'T_I' (UNIQUE) (Cost= 310  Card= 27240  B
          ytes= 735480 )




SQL> alter index t_i unusable;

Index altered.

SQL> alter session set skip_unusable_indexes=true;

Session altered.

SQL> select object_name from t order by object_id ;

Execution Plan
----------------------------------------------------------
    0       SELECT STATEMENT Optimizer=CHOOSE (Cost= 430  Card= 27240  Bytes
          = 735480 )

    1      0    SORT (ORDER BY) (Cost= 430  Card= 27240  Bytes= 735480 )
    2      1      TABLE ACCESS (FULL) OF 'T' (Cost= 88  Card= 27240  Bytes= 735 
           480 )




SQL> select /*+ index (t,t_i) */ object_name from t order by object_id ;
select /*+ index (t,t_i) */ object_name from t order by object_id
*
ERROR at line  1 :
ORA- 01502 : index 'SYSTEM.T_I' or partition of such index is in unusable state


SQL> alter index t_i rebuild;

Index altered.

SQL> desc t
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OWNER                                     NOT NULL VARCHAR2( 30 )
 OBJECT_NAME                               NOT NULL VARCHAR2( 30 )
 SUBOBJECT_NAME                                     VARCHAR2( 30 )
 OBJECT_ID                                 NOT NULL NUMBER
 DATA_OBJECT_ID                                     NUMBER
 OBJECT_TYPE                                        VARCHAR2( 18 )
 CREATED                                   NOT NULL DATE
 LAST_DDL_TIME                             NOT NULL DATE
 TIMESTAMP                                          VARCHAR2( 19 )
 STATUS                                             VARCHAR2( 7 )
 TEMPORARY                                          VARCHAR2( 1 )
 GENERATED                                          VARCHAR2( 1 )
 SECONDARY                                          VARCHAR2( 1 )

SQL> alter table t modify(object_id null, owner null,object_name null,
   2   created null,last_ddl_time null);

Table altered.

SQL> insert into t(object_id) values(null);

 1  row created.


Execution Plan
----------------------------------------------------------
    0       INSERT STATEMENT Optimizer=CHOOSE (Cost= 1  Card= 1  Bytes= 96 )



SQL> select /*+ index (t,t_i) */ object_name from t order by object_id ;

Execution Plan
----------------------------------------------------------
    0       SELECT STATEMENT Optimizer=CHOOSE (Cost= 430  Card= 27240  Bytes
          = 735480 )

    1      0    SORT (ORDER BY) (Cost= 430  Card= 27240  Bytes= 735480 )
    2      1      TABLE ACCESS (FULL) OF 'T' (Cost= 88  Card= 27240  Bytes= 735 
           480 )




SQL> 

P.S. Не надо корчить из себя супер-пупер специалиста, неся при этом чушь и считая других идиотами.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098460
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ы
P.S. Не надо корчить из себя супер-пупер специалиста, неся при этом чушь и считая других идиотами.

Во-первых, не хами. Ты в своих постах нахамил мне, абсолютно незнакомому тебе человеку, уже два раза. Этого делать не надо.

Во-вторых, своим примером ты показал, что если в хинте указаны индексы в состоянии UNUSABLE , то не сработает и сам запрос. Что и требовалось доказать.

А то в приведённой выше дискуссии некоторые её участники ошибочно считают, что если в хинте указан индекс в состоянии UNUSABLE , то CBO просто обойдёт этот индекс.

Это мнение полностью ошибочно и действительности не соответствует. Хотя как раз это мнение и является основным аргументом пуристов SQL.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098512
Владимир Бегун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квасной
Это мнение полностью ошибочно и действительности не
соответствует. Хотя как раз это мнение и является основным
аргументом пуристов SQL.
http://groups-beta.google.com/group/fido7.ru.rdbms.oracle/msg/b81a57eace92752a?hl=en

цитата
> Я не уверен что Вы получите _гарантировонный_ результат,
> особенно при распаралеливании запроса

> Гарантий только две ORDER BY или ..

Гарантия одна ORDER BY, те кто знает когда им ORDER BY
не нужен им и не пользуются. Мы же это уже несколько сот
раз обсуждали.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098520
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КваснойВо-вторых, своим примером ты показал, что если в хинте указаны индексы в состоянии UNUSABLE , то не сработает и сам запрос. Что и требовалось доказать.Так именно это тебе и показывают - бывают ситуации, когда программа должна отработать любой ценой (VIP-клиент ждет, начальство отчет требует и т.д.), а админ временно недоступен и перестроить индекс некому. И попробуй объяснить начальнику, что писался супер-пупер оптимизированный запрос под определенное поведение оракла, а тут оракл отказался так себя вести. А тут еще подтянется админ и выскажет вышеприведенные соображения. КваснойА то в приведённой выше дискуссии некоторые её участники ошибочно считают, что если в хинте указан индекс в состоянии UNUSABLE , то CBO просто обойдёт этот индекс.

Это мнение полностью ошибочно и действительности не соответствует. Хотя как раз это мнение и является основным аргументом пуристов SQL.Насколько я помню ту дискуссию, там этого не утверждалось (да это и легко проверяется)

По поводу правильности данных - индекс ведь может быть не только UNUSABLE, но и просто убит (админ решил инсерты оптимизировать или прибили на время заливки большого объема данных и забыли поднять). Вот тогда будет именно НЕПРАВИЛЬНЫЙ результат (и молчаливо, притом). А то есть любители искать минимальное:
Код: plaintext
tst> create table t123(x not null) as\n   2   select  2  from dual union all\n   3   select  1  from dual union all\n   4   select  3  from dual;\n\nTable created.\n\ntst> create index idx_t123_x on t123(x);\n\nIndex created.\n\ntst> set autotrace on exp\ntst> select /*+ index(t123, idx_t123_x) */ * from t123 where rownum= 1 ;\n\n         X\n----------\n          1 \n\n 1  row selected.\n\n\nExecution Plan\n----------------------------------------------------------\n    0       SELECT STATEMENT Optimizer=CHOOSE (Cost= 27  Card= 1  Bytes= 13 )\n    1      0    COUNT (STOPKEY)\n    2      1      INDEX (FULL SCAN) OF \'IDX_T123_X\' (NON-UNIQUE) (Cost= 27  Card= 327  Bytes= 4251 )\n\n\n\ntst> drop index idx_t123_x;\n\nIndex dropped.\n\ntst> select /*+ index(t123, idx_t123_x) */ * from t123 where rownum= 1 ;\n\n         X\n----------\n          2 \n\n 1  row selected.\n\n\nExecution Plan\n----------------------------------------------------------\n    0       SELECT STATEMENT Optimizer=CHOOSE (Cost= 3  Card= 1  Bytes= 13 )\n    1      0    COUNT (STOPKEY)\n    2      1      TABLE ACCESS (FULL) OF \'T123\' (Cost= 3  Card= 327  Bytes= 4251 )\n\n
Самое смешное, что простое добавление ORDER BY нисколько не утяжелит запрос (никто не запрещает использовать и хинты), но всегда гарантирует правильный результат

Еще одно соображение - есть любители использовать обработчик WHEN OTHERS THEN := значение по-умолчанию, дескать не нашли мы требуемого значения (NO_DATA_FOUND) или их больше одного (TOO_MANY_ROWS) или по формату не приводится/длина не та (VALUE_ERROR) или еще чего-нибудь, не удовлетворяющее нашим проверкам, короче, неподходит нам эта строка - нафига все перечислять, просто напишу WHEN OTHERS. А строка-то подходит, просто индекс UNUSABLE. Это ведь тоже неправильный результат.

Конечно, можно разволноваться и кричать, что все это криворукие админы/программеры, но, к сожалению, это встречается на каждом шагу. Поэтому программа должна себя вести как лифт: Аркадий и Борис Стругацкие. Сказка о тройке...
Но монтеры со своей стороны должны обеспечивать бесперебойность. Ничего, понимаете, ссылаться на объективные обстоятельства. У нас лозунг: "лифт для всех". Не взирая на лица. Лифт должен выдержать прямое попадание в кабину самого необученного академика .
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098556
ы
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ы
Гость
Квасной...
Поэтому и приходится использовать хинты для явного прописывания логики запроса...
...Что же до порядка строк — так он при корректном прописывании пути доступа по индексу тоже гарантирован...
...Ответ на этот вопрос такой: «следует использовать хинт для доступа по индексу»...
...На этот месте обычно следуют рассказы о том что случится, если индекс станет UNUSABLE. Мне до сих пор интересно: найдётся ли хоть один человек, который перед тем, как высказать такое опасение, сделает-таки индекс UNUSABLE и посмотрит, что произойдёт на самом деле? Ну просто из любопытства...
ыP.S. Не надо корчить из себя супер-пупер специалиста, неся при этом чушь и считая других идиотами.
Это что - не чушь? Причем безаппеляционно выдаваемая за истину в последней инстанции? Я так понимаю, что все-таки нашлись такие "человеки", которые проверили? Сюда (на sql.ru) заглядывают и серьезные дядьки - только это я и имел виду. Не надо считать себя умнее всех. Чаще всего это не так :)

что касается
ыЯ за такие ответы бью "Oracle Database Error Messages" по голове. До наступления просветления. Другие кишки тупым ножом выпускают :)
то, во-первых, это лично к тебе/Вам не относится - я так буду поступать со всеми, не смотря на звания и регалии. Во-вторых, обрати внимание на смайлик :)

P.S. Не воспринимай все лично на свой счет. Чуть поменьше распальцовка :), осторожность в выражениях никому не помешают. Извини, если обидел.

ElicЯ не собираюсь упорствовать в твоем разубеждении. Тебя научит жизнь.
Присоединяюсь. Bye.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33098691
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КваснойВ общем, всё в лучших традициях религий мира: ссылки на мифическую «жизнь» вместо примеров того, когда предложенная конструкция не работает :)По существу сказано же достаточно. А по поводу твоей личной религии - это ты в точку :)
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33100878
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вячеслав ЛюбомудровСамое смешное, что простое добавление ORDER BY нисколько не утяжелит запрос (никто не запрещает использовать и хинты), но всегда гарантирует правильный результат

Oh my god...

Перечитайте моё сообщение.

Не работает тут ORDER BY , понимаете?

Oracle не поддерживает передачу полей из запроса во вложенные запросы FIELD SUBQUERY .

Вот так:
Код: plaintext
1.
2.
3.
4.
5.
SELECT	(
	SELECT	dummy
	FROM	dual di
	WHERE	di.dummy = do.dummy
	)
FROM	dual do

работает.

А вот так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
SELECT	(
	SELECT	dummy
	FROM	(
		SELECT	dummy
		FROM	dual di
		WHERE	di.dummy = do.dummy
		ORDER BY
			dummy
		)
	WHERE	rownum =  1 
	)
FROM	dual do

не работает.

Я же не против ORDER BY как такового :)

ORDER BY — отличная конструкция, ею отсортировано уже не менее миллиарда запросов в мире.
ORDER BY обеспечивает правильный порядок фамилий в зарплатной ведомости.
ORDER BY выдаёт финансовым аналитикам отсортированный список решений.
Без ORDER BY мы бы запутались в выписке телефонных переговров Би-лайн...

Да чего уж там, очень много вещей, к которым мы привыкли сейчас, возможны только благодаря ORDER BY !

Но только в тех случаях, когда она не работает, надо не искать гарантий, а что-то делать.

Вячеслав Любомудров
Еще одно соображение - есть любители использовать обработчик WHEN OTHERS THEN := значение по-умолчанию, дескать не нашли мы требуемого значения (NO_DATA_FOUND) или их больше одного (TOO_MANY_ROWS) или по формату не приводится/длина не та (VALUE_ERROR) или еще чего-нибудь, не удовлетворяющее нашим проверкам, короче, неподходит нам эта строка - нафига все перечислять, просто напишу WHEN OTHERS. А строка-то подходит, просто индекс UNUSABLE. Это ведь тоже неправильный результат.


Я к таким любителям не отношусь и никому так делать не советую.

Однако к сортировке запросов это не имеет ни малейшего отношения :)

Вячеслав Любомудров
Конечно, можно разволноваться и кричать, что все это криворукие админы/программеры, но, к сожалению, это встречается на каждом шагу. Поэтому программа должна себя вести как лифт: Аркадий и Борис Стругацкие. Сказка о тройке...
Но монтеры со своей стороны должны обеспечивать бесперебойность. Ничего, понимаете, ссылаться на объективные обстоятельства. У нас лозунг: "лифт для всех". Не взирая на лица. Лифт должен выдержать прямое попадание в кабину самого необученного академика .

Ну это...

Мне неловко вам напоминать такую очевидную вещь, но если CBO , даже безо всяких хинтов, и с аккуратнейшим использованием ORDER BY , вдруг да и решит использовать индекс, который находится в состоянии UNUSABLE , то запрос вылетит по той же самой ORA-01502 .

Это к вопросу о лифте, который выдерживает прямое попадание CB ... простите, академика.

Хотя что это я.

Ведь у всех хороших програмистов, читавших Стругацких, процедуры, несомненно, корректно обрабатывают ORA-01502 (и именно её), без использования WHEN OTHERS .

Не так ли? :)

А если серьёзно, то программа должна себя вести не как лифт. Программа должна вести себя так, как прописано в ТЗ.

Если в ТЗ прописано, что программа должна быстро работать в 99,99% случаев, при этом допускается её отказ в 0,01% случаев, — то делать надо так, чтобы она работала быстро.

Если в ТЗ прописано, что программа должна работать в 100% случаев, то надо делать так, чтобы она работала правильно.

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

Как это так: он решил переименовать, или, тем более, удалить уникальный индекс?

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

Скажем, так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
DECLARE
	cnt	NUMBER;
	index_unusable	EXCEPTION;
	PRAGMA EXCEPTION_INIT(index_unusable, - 1502 );
BEGIN
	BEGIN
		SELECT	NULL
		INTO	cnt
		FROM	dba_indexes
		WHERE	owner = SYS_CONTEXT('userenv', 'current_schema')
			AND index_name = 'UX_RATE_CURRENCY_DATE';
	EXCEPTION
	WHEN no_data_found THEN
		RAISE index_unusable;
	END;
	OPEN	:cur
	FOR	SELECT	(
			SELECT	/*+ INDEX_DESC (r ux_rate_currency_date) */
				rte_rate
			FROM	t_rate
			WHERE	rte_currency = acm_currency
				AND rte_date <= acm_date
				AND rownum =  1 
			) * acm_sum
		FROM 	t_accmove;
EXCEPTION
WHEN index_unusable THEN
	OPEN	:cur
	FOR	SELECT	(
			SELECT	/*+ FULL(r) */
				MAX(rte_rate) KEEP (DENSE_RANK LAST ORDER BY rte_date)
			FROM	t_rate r
			WHERE	rte_currency = acm_currency
				AND rte_date <= acm_date
			) * acm_sum
		FROM	t_accmove;
	DBMS_OUTPUT.put_line('Администратор базы данных, козлина тупая, чё-то сделал с уникальным индексом,');
	DBMS_OUTPUT.put_line('от которого, вообще-то, зависит логика работы базы.');
	DBMS_OUTPUT.put_line('Из-за этого ваша программа работает медленно, а скоро ещё и наделает ошибок.');
	DBMS_OUTPUT.put_line('Позвоните хозяину фирмы, пускай он выпишет администратору п' ||
		CHR( 232 ) || CHR( 231 ) || CHR( 228 ) || CHR( 238 ) || 'в, да покрепче');
END;

Чем плохо? :)

У меня , кстати, такая конструкция, без ORDER BY , уже года три работает на production в чуть больше чем тридцати местах.

Пока, тьфу-тьфу, держимся :)
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33100882
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владимир Бегун цитата
> Я не уверен что Вы получите _гарантировонный_ результат,
> особенно при распаралеливании запроса

> Гарантий только две ORDER BY или ..

Гарантия одна ORDER BY, те кто знает когда им ORDER BY
не нужен им и не пользуются. Мы же это уже несколько сот
раз обсуждали.

Ну слава богу. Уважаемый человек говорит, что есть гарантии .

А то я вот не так давно читал такое:
Oracle Technology Network Development and Distribution License TermsTHE PROGRAMS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND . WE FURTHER DISCLAIM ALL WARRANTIES, EXPRESS AND IMPLIED, INCLUDING WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.

IN NO EVENT SHALL WE BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE, DATA OR DATA USE, INCURRED BY YOU OR ANY THIRD PARTY, WHETHER IN AN ACTION IN CONTRACT OR TORT, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Это, в частности, значит, что Oracle не гарантирует , что запрос будет отсортирован правильно, даже при использовании ORDER BY .

Как показывает практика , ORDER BY сортирует значения правильно. Это всё , что мы можем сказать об использовании ORDER BY .

Я даже документацию читал. Да вот только она попадает под то же лицензионное соглашение, которое ничего не гарантирует .

Но мне тут уже неоднократно говорили о каких-то гарантиях того, что ORDER BY всё отсортирует, как надо.

Владимир, где я могу про упомянутые вами гарантии прочитать подробнее?
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33100885
Владимир Бегун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КваснойЭто, в частности, значит, что Oracle не гарантирует, что запрос будет отсортирован правильно, даже при использовании ORDER BY.
Нет, это (и даже не в частности) можно назвать попыткой расширить субъект тезиса. Этого делать не нужно.

Расшифровываю относительно лицензии:

Если, скажем, из-за какой-то недоделки ORDER BY не будет правильно (согласно документации) сортировать данные, то ты не можешь подать за это в суд и требовать возмещения убытков и проч. Вот именно об этом и написано в лицензии. Но это поведение и ответ Oracle по поводу недоделки будет железным агрументом в твою пользу и ты сможешь смело сказать: "Начальник, это bug #12345678. Ждём исправления". Т.е. с технической точки зрения, открытый эскалированный (если мощи лицензии хватит) TAR/bug позволит тебе получить исправление.

Теперь о слове "гарантия". Я упоминал его именно в том смысле в каком оно указано в документации, а именно:

Oracle9i SQL Reference Release 2 (9.2)
order_by_clause

Use the ORDER BY clause to order rows returned by the statement. Without an order_by_clause, no guarantee exists that the same query executed more than once will retrieve rows in the same order.

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

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

Я не могу не согласиться (зависит от понимания проблемы и ситуации), что иногда только так (index=source of pre-ordered data) и можно добиться нужной скорости выборки, но в целом, "without an order_by_clause, no guarantee exists that the same query executed more than once will retrieve rows in the same order". Я думаю этого достаточно, чтобы понять, что тех. поддержка тебя вышлет, если ты будешь им рассказывать о своей жизненной позиции по поводу использования индекса.

Если у тебя требования только обеспечить скорость и ты её обеспечиваешь написав такой код и все счастливы -- радуйся жизни. Если что-то сломается и тебя "не поймут", тогда сам решишь, что лучше -- "крепко спать" или "быстро бегать" ("бегать" в смысле на работу, к заказчику и проч. и исправлять ситуацию).

Всё нужно делать с умом.

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

Забавно, что с завидной переодичностью эта тема всплывает то там то сям... :-)

P.S.: Беседа на счёт смысла слов и их понимания, мне, честно говоря, мало интересна, поэтому если ты хочешь её продолжить, не расчитывай на моё в ней участие.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33101306
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Владимир БегунЯ думаю этого достаточно, чтобы понять, что тех. поддержка тебя вышлет, если ты будешь им рассказывать о своей жизненной позиции по поводу использования индекса.
Можно по поводу этого поподробнее?

Мои рассуждения строятся на двух предположениях:

1. Указанный хинт заставляет CBO использовать метод доступа INDEX RANGE SCAN DESCENDING .

Oracle9i Database Performance Tuning Guide and ReferenceSpecifying one of these hints causes the optimizer to choose the specified access path only if the access path is available based on the existence of an index or cluster and on the syntactic constructs of the SQL statement. If a hint specifies an unavailable access path, then the optimizer ignores it.
В данном случае мы будем предполагать, что индекс с заданным названием существует.

Из данного предложения следует, что если индекс существует, и синтаксическая конструкция запроса позволяет использовать указанный в хинте метод доступа к таблице, то хинт заставляет CBO использовать заданный метод доступа.

Вопрос: будет ли считаться багом ситуация, когда хинт указывает метод доступа INDEX RANGE SCAN DESCENDING по существующему индексу, конструкция запроса позволяет использовать этот метод, а CBO , вопреки тому, что написано в документации, этот метод не использует?

2. Если используется метод доступа INDEX RANGE SCAN DESCENDING , то значения возвращаются отсортированными по убыванию величины индексированных полей.

Oracle9i Database Performance Tuning Guide and ReferenceThe INDEX_DESC hint explicitly chooses an index scan for the specified table. If the statement uses an index range scan, then Oracle scans the index entries in descending order of their indexed values.
, и оттуда же:
Oracle9i Database Performance Tuning Guide and ReferenceAn index range scan descending is identical to an index range scan , except that the data is returned in descending order. Indexes, by default, are stored in ascending order. Usually, this scan is used when ordering data in a descending order to return the most recent data first, or when seeking a value less than a specified value.
Вопрос: будет ли считаться багом ситуация, в которой Oracle при использовании данного метода доступа возвращает строки не в порядке убывания величины индексированных полей, а в каком-то ином порядке, не соответствующем тому, что написано в документации?

Заранее спасибо за ответ.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33101616
gz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
gz
Гость
КваснойОбычные джойны с группировкой и сортировкой работают медленно, и тут нам на помощь приходит хитрость. Блюстители чистоты SQL меня, конечно, засмеют, ну да мне не привыкать :)
Самое интересное в том, что Вы прекрасно понимаете, что это хитрость. Позвольте сделать одно предположение - над Вами нет начальника, понимающего эти проблемы. В противном случае Вы бы вылетели с работы после пары таких "закидонов".
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33101680
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квасной Вопрос : будет ли считаться багом ситуация, когда хинт указывает метод доступа INDEX RANGE SCAN DESCENDING по существующему индексу, конструкция запроса позволяет использовать этот метод, а CBO , вопреки тому, что написано в документации, этот метод не использует?


Well, lets not twist the facts:

Oracle9i Database Performance Tuning Guide and Reference. GlossaryCBO
Cost-based optimizer. Generates a set of potential execution plans for SQL statements, estimates the cost of each plan, calls the plan generator to generate the plan, compares the costs, and chooses the plan with the lowest cost . This approach is used when the data dictionary has statistics for at least one of the tables accessed by the SQL statements. The CBO is made up of the query transformer, the estimator, and the plan generator.

So the fact CBO will not use a hint because it conlicts with plan CBO considers optimal is normal and is not a bug:

Oracle9i Database Performance Tuning Guide and Reference Release 2 (9.2) Optimizer Hints Specifying a Full Set of Hints
When using hints, in some cases, you might need to specify a full set of hints in order to ensure the optimal execution plan. For example, if you have a very complex query, which consists of many table joins, and if you specify only the INDEX hint for a given table, then the optimizer needs to determine the remaining access paths to be used, as well as the corresponding join methods. Therefore, even though you gave the INDEX hint, the optimizer might not necessarily use that hint, because the optimizer might have determined that the requested index cannot be used due to the join methods and access paths selected by the optimizer.

Anyway, bottom line: only ORDER BY guarantees ordered resultset - using something else is just a ticking bomb.

SY.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33101751
Квасной
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SY Квасной Вопрос : будет ли считаться багом ситуация, когда хинт указывает метод доступа INDEX RANGE SCAN DESCENDING по существующему индексу, конструкция запроса позволяет использовать этот метод, а CBO , вопреки тому, что написано в документации, этот метод не использует?

Well, lets not twist the facts:

Oracle9i Database Performance Tuning Guide and Reference. GlossaryCBO
Cost-based optimizer. Generates a set of potential execution plans for SQL statements, estimates the cost of each plan, calls the plan generator to generate the plan, compares the costs, and chooses the plan with the lowest cost . This approach is used when the data dictionary has statistics for at least one of the tables accessed by the SQL statements. The CBO is made up of the query transformer, the estimator, and the plan generator.

So the fact CBO will not use a hint because it conlicts with plan CBO considers optimal is normal and is not a bug:

Oracle9i Database Performance Tuning Guide and Reference Release 2 (9.2) Optimizer Hints Specifying a Full Set of Hints
When using hints, in some cases, you might need to specify a full set of hints in order to ensure the optimal execution plan. For example, if you have a very complex query, which consists of many table joins, and if you specify only the INDEX hint for a given table, then the optimizer needs to determine the remaining access paths to be used, as well as the corresponding join methods. Therefore, even though you gave the INDEX hint, the optimizer might not necessarily use that hint, because the optimizer might have determined that the requested index cannot be used due to the join methods and access paths selected by the optimizer.

Question: if I do specify full set of hints (with a STORED OUTLINE , for instance, or with hints as such), all tables and indexes do exist and are is usable state, then do I ensure the execution plan?

Note that there are no table joins in the FIELD SUBQUERY above.

And again,

Question: if CBO does use INDEX RANGE SCAN DESCENDING and returns rows not in descending order of indexed values (as said in specification), will it be considered a bug?

SYAnyway, bottom line: only ORDER BY guarantees ordered resultset - using something else is just a ticking bomb.
I have read the manuals and I have heard this sentence several hundred times before.

If one has a tiniest possibility to use ORDER BY clause, he must use it

There are some situations when ORDER BY clause is unavailable (see example above)

Once again: there are some situations when ORDER BY clause is unavailable (see example above)

The method described handles these situations correctly.

This method is intended for usage only in situations when ORDER BY clause is unavailable (see example above)

This method does conform to the specifications and it is tested on production systems.

ORDER BY clause does guarantee data order, but it cannot be used in some queries (see example above)
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33101762
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КваснойOnce again: there are some situations when ORDER BY clause is unavailable (see example above)
Всегда найдутся пути ( например ) разрешения подобной проблемы без ущерба правильности результата .
КваснойThe method described handles these situations correctly.
Твои слова да богу в уши!
КваснойThis method does conform to the specifications and it is tested on production systems.
Даже тысячи успешных экспериментов не смогут превратить "лженаучную" () гипотезу в теорию.



Ты уже сделал свой выбор. Бог с тобой. Неси свой крест сам.
Но не надо пытаться привлекать за собой в эту странную религию другие неокрепшие умы.
...
Рейтинг: 0 / 0
Выборка уникальных значений из хронологической таблицы
    #33101763
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КваснойQuestion: if I do specify full set of hints (with a STORED OUTLINE, for instance, or with hints as such), all tables and indexes do exist and are is usable state, then do I ensure the execution plan?

Well, problem is it is difficult (at least for me) to determine what constitutes a full set of hints for a specific SQL statement. In terms of STORED OUTLINES, CBO should use same plan, however, in general, it might require certain INIT.ORA parameters be set same way (for example, QUERY_REWRITE_ENABLED, STAR_TRANSFORMATION_ENABLED, OPTIMIZER_FEATURES_ENABLE).

КваснойQuestion: if CBO does use INDEX RANGE SCAN DESCENDING and returns rows not in descending order of indexed values (as said in specification), will it be considered a bug?

No. For a simple reason you heard "several hundred times before". Besides, if you are joining tables, CBO might use index in desc order but then use hash join or some sort of conversion to bitmap which will affect resultset row order or simply whoever wrote CBO code felt like it. All INDEX_DESC hint tells CBO is how to access the table - it does not tell it to return it in desc or any other, for that matter, order.

SY.
...
Рейтинг: 0 / 0
25 сообщений из 59, страница 1 из 3
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Выборка уникальных значений из хронологической таблицы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]