|
|
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
Хотелось бы узнать у уважаемых форумистов является ли подзапрос полным эквивалентом обычной таблицы в запрсе. Что я под этим понимаю? Применимы ли к результату подзапроса все операции что и к обычной таблице. То есть соединение с другими таблицами, объединение, группировка по полям, сортировка агрегатные функции. Понятно, что результат подзапроса представляет собой с точки зрения теории ту же реляционную таблицу, но будут ли применимы к ней ВСЕ операции (все ключевые слова, функции и т.п.). Есть ли какие-то ограничения на использование подзапросов в определенных конструкциях? Есть ли такие места где обычная таблица может использоваться, а подзапрос нет? Почему я это спрашиваю. Передо мной стоит задача перевод с собственного языка запросов в T-SQL. В моем языке запросов будут иметь место такие конструкции, когда нужно будет запись к одному объекту заменить не напрямую на запрос к одной таблице, а на запрос к нескольким таблицам (то есть на некоторый подзапрос). Сделать это можно двумя способами: 1. (Как делаю я сейчас) Запрос типа select a.b,c.d from a,c where a.e = c.f заменять на такую конструкцию select a.b,c_1.d from a,c_1 where a.e = c_1.f union all select a.b,c_2.d from a,c_2 where a.e = c_2.f Надеюсь пример понятен - то есть всю простые таблицы мы вносим внутрь сложного запроса 2. Как хотелось бы (так проще) select a.b,c_1.d from a, ( select c_1.d,c_1.f from c_1 union all select c_2.d,c_2.f from c_2 ) c where a.e = c.f Во втором случае также меня терзают сомнения насчет эффетивности. Дело в том, что в общем запрос мы может писать так select a.b,c.d from a,c where a.e = c.f and a.l = 1000 То есть задаем некое ограничение, которое в первом случае будет также переносится в каждую составляющую union, во втором же случае фильтрация будет осущствляться позже. Хотя может быть во втором случае оптимизатор сможет найти зависимость и внесет ограничение внутрь подзапроса? Это меня также волнует может быть даже больше чем ограничения на использование подзапросов Вот так вот. Длинно, но думаю понятно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2002, 10:25:10 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
Есть ли какие-то ограничения на использование подзапросов в определенных конструкциях? Есть ли такие места где обычная таблица может использоваться, а подзапрос нет? Ограничения, конечно, есть BOL - Accessing and Changing Relational Data - Advanced Query Concepts - Subquery Fundamentals - Subquery Rules Хотя может быть во втором случае оптимизатор сможет найти зависимость и внесет ограничение внутрь подзапроса? Всегда можно идти от обратного: имееются запросы такого типа, как "заставить" оптимизатор выбрать наилучшиий план выполнения. Либо неявно - с помощью создания тех же индексов Либо явно - с помощью хинтов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2002, 16:06:27 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
Ограничения, конечно, есть BOL - Accessing and Changing Relational Data - Advanced Query Concepts - Subquery Fundamentals - Subquery Rules Спасибо. Не понятны следующие пункты: If the WHERE clause of an outer query includes a column name, it must be join-compatible with the column in the subquery select list. Because they must return a single value, subqueries introduced by an unmodified comparison operator (one not followed by the keyword ANY or ALL) cannot include GROUP BY and HAVING clauses. ORDER BY can only be specified if TOP is also specified (понятно, но не понятно почему такое ограничение) Всегда можно идти от обратного: имееются запросы такого типа, как "заставить" оптимизатор выбрать наилучшиий план выполнения. Либо неявно - с помощью создания тех же индексов Либо явно - с помощью хинтов. Нет. Здесь немного другая проблема, которая индексами и хинтами не решается. Скажем вот в таком запросе: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. поймет ли оптимизатор, что не стоит выполнять ползапрос по всем строкам, а только по тем, которые в таблице a удовляеторяют условию and a.l = 100. В таблицах c_1,c_2 может быть миллион записей, но накладывая условие and a.l = 100 мы может ограничить их количество до 1. Вот в чем вопрос. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2002, 16:23:39 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
Давайте определися для начала subquery - это subquery derived table - это derived table Ссылка в BOL именно для subquery. поймет ли оптимизатор, что не стоит выполнять ползапрос по всем строкам, а только по тем, которые в таблице a удовляеторяют условию and a.l = 100. Условие a.l = 100 не накладывает никаких ограничений на derived table, полученную из таблиц c_1 и c_2. Для того, чтобы выяснить, имеется ли в derived table какая-нибудь запись из таблицы "а", нужно оперировать со всей derived table. А вот каким образом будет осуществляться join между "а" и derived table можно попробовать регулировать с помощью индексов и хинтов. Вполне вероятно, что для derived table, полученных из объединения нескольких таблиц, в оптимизации запроса могут помочь и partitioned views (но это если версия позволяет). Конечно, оптимизатор не идеален, так что, если можете помочь ему, то помогайте. Например, если вам известно, что для записей с a.l = 100 имеются записи только в таблице c_2, то и стройте свой запрос соответсвующим образом (все рано вы ведь делаете это динамически ?) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2002, 17:54:41 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
Вобщем либо я не врубаюсь, либо вы (ты). Еще раз. Имеем запрос на моем языке Код: plaintext 1. 2. который переводится в запрос на T-SQL двумя способами 1) Как мне хотелось бы. Код: plaintext 1. 2. 3. 4. 5. 6. 7. Поясню почему. Потому что таблица "с" в запросе просто заменяется на подзапрос/или подчиненную таблицу - здесь без разницы. 2) Как делаю сейчас Код: plaintext 1. 2. 3. 4. Поясню почему. Как мне кажется такой вариант более эффективен потому что в каждом select отсекаются лишние записи. При этом нужно учесть что это простые запросы, а могут быть сложнее - там где есть агрегатные функции, группировка, сортировка и т.п. в каждом select входящем в union. Вот и возникает вопрос будет ли сравним вариант 1) с вариантом 2) по скорости выполнения если в объединении таблиц c_1,c_2 много записей, но если наложить условие как описано выше после "внесения" их в каждый select количество записей значительно уменьшается. Поймет ли (оценит ли) это оптимизатор? Сможет ли сам сделать такое преобразование? Короче я сейчас проверяю. Просто думал может кто знает чисто теоретически. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2002, 18:33:56 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
Проверил. При наличии нужных индексов 1 вариант получился даже лучше! Теперь стоит подумать и проверить, что будет без индексов. Честно говоря я удивлен таким возможностям оптимизатора. Я конечно подозревал, что так может быть (даже что должно), но, что так есть на самом деле... з.ы. По плану запроса было видно, что он внес соответствующие условия внутрь select-ов тем самым резко ограничив объем обрабатывемой информации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2002, 19:10:15 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
соответсвующие условия внутрь оптимизатор переносит далеко не вегда и только для простых подзапросов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2002, 11:15:01 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
соответсвующие условия внутрь оптимизатор переносит далеко не вегда и только для простых подзапросов. А где можно про это почитать? Или может есть какие-то известные правила? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2002, 11:33:40 |
|
||
|
Подзапрос = обычная таблица в запросе?
|
|||
|---|---|---|---|
|
#18+
Проверил еще на одном запросе. Вот два варианта: Код: plaintext 1. 2. 3. 4. 5. 6. 7. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Здесь уже оптимизатор не переносит условия внутрь. Но всеравно разница во времени выполнения небольшая. Хотя второй вариант выполняется несколько быстрее. Еще хотел бы спросить - как правильно производить сравнение скорости выполнения запросов. Во-первых чем? Во-вторых, что нужно сделать, чтобы были равные условия. Как делаю сейчас. Первое - замеряю с помощью SQL Profiler по колонкам Start time, End time. Второе - перегружаю SQL Server. Правильно ли я поступаю? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2002, 12:09:47 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32048954&tid=1820509]: |
0ms |
get settings: |
7ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
98ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
32ms |
get tp. blocked users: |
1ms |
| others: | 235ms |
| total: | 402ms |

| 0 / 0 |
