Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Учет движения  [new]
MrBlackJack
Member

Откуда:
Сообщений: 43
Добрый день, уважаемые форумчане!
Есть следующая таблица:
DateBegin DateEnd Nomer Mol
2011-03-23 00:00:00.000 2011-08-16 00:00:00.0007166 Дмитрий
2011-08-16 00:00:00.000 2012-03-27 00:00:00.0007166 Александр

Учет движения оборудования, где
DateBegin - дата передачи
DateEnd - дата возврата
Nomer - серийный номер оборудования
Mol - Лицо ответственное за это оборудование
Бывают ситуации когда в один месяц одно и тоже оборудование передавалась и возвращалась несколько раз.
Запрос к этой таблице должен быть параметризованный, передаются дата начала анализа и дата окончания..Например период анализа с 20110801 по 20110831 (полный месяц)
Результат должен соответствовать следующим требованиям:
- Дата возврата должна быть не менее заданной даты окончания, т.е. DateEnd >= 20110831
- DateBegin < даты окончания
- Теперь самое непонятное (для меня) если в рамках одного месяца было несколько возвратов/передач, то учитывать эти строки тоже, как в данном случае...Оборудование вернули посреди месяца (2011-08-16 00:00:00.000), а потом в этот же день передали снова.
Заранее спасибо, надеюсь на вашу поддержку!
7 авг 12, 16:06    [12976211]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
1. Самое главное: Что нужно вернуть? В чём задача?
2. DateEnd не имеет никакого смыла в данной задаче DateEnd всегда равен DateBegin следующей записи по данному оборудованию.
3. А вы знаете что время непрерывно? Поэтому период задаётся точками в котором одна точка выколота:
DECLARE	 @From	Date	= '20110801'
	,@To	Date	= '20110901'
WHERE	    [Date] >= @From
	AND [Date] <  @To
И тогда вы не отгребёте проблем.

Чтобы обойти проблему производительности, то вот одно из решений:
-- Состояние на начало периода
	SELECT	M.*
	FROM	dbo.Fund F CROSS APPLY (
		SELECT	Top(1) M.*
		FROM	dbo.FundMovement M
		WHERE	M.Fund = F.ID
		ORDER BY M.[Date]	) M
	WHERE	M.[Date] < @From
UNION ALL
-- Движения за период
	SELECT	*
	FROM	dbo.FundMovement
	WHERE	    [Date] >= @From
		AND [Date] <  @To
Если в таблице оборудования есть даты выхода их оборота, то ещё лучше (нужно добавить условие).
7 авг 12, 18:12    [12977008]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
MrBlackJack
Member

Откуда:
Сообщений: 43
Mnior
1. Самое главное: Что нужно вернуть? В чём задача?
2. DateEnd не имеет никакого смыла в данной задаче DateEnd всегда равен DateBegin следующей записи по данному оборудованию.
3. А вы знаете что время непрерывно? Поэтому период задаётся точками в котором одна точка выколота:

На самом деле немного не так...Таблица, что в первом сообщение - это результат запроса. Структура же реальной таблицы - это список документов, с полями Дата - дата движения, тип движения - 1 - передача клиенту, 2 - возврат на склад от клиента и т.д. Эти документы объединяются в пары (передача - возврат),
Дата Тип движения Номер
2011-03-23 00:00:00.000 1 23
2011-08-16 00:00:00.000 2 23
2011-08-16 00:00:00.000 133
2012-03-27 00:00:00.000 2 33

Приводил я их к такому виду для того, чтобы посчитать количество дней в эксплуатации...Я разбивал оборудование на такие пары, считал количество дней, складывал - получал общее.
Бывают ситуации когда оборудование вернули от клиента и оно провалялось на складе какое-то время, пока его снова не передали клиенту, например
Дата Тип движения Номер
2011-03-23 00:00:00.000 1 23
2011-08-16 00:00:00.000 2 23
2011-08-18 00:00:00.000 133
2012-03-27 00:00:00.000 2 33
8 авг 12, 09:31    [12979061]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
MrBlackJack, есть такая особенность в пока ещё соффремённых "декларативных" языках, что необходимо как можно меньше и как можно точно использовать промежуточную форму описания/формализации. Оно хорошо для предварительного проектирования, но для основного не очень. Мало какие языки содержат элементы структурной оптимизации. В основном это из-за того что используемые формализмы нечисты и содержат императивщину, ну и особенности (мощность) языка.

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

И их у вас тут две:
1. представление периодов
2. выборка данных (движений) за период

Сначала нужно выбрать нужные данные, а потом оформить в нужном виде, а не наоборот. Порядок меняет "смысл".
8 авг 12, 12:30    [12980710]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
MrBlackJack,

А те интервалы использования оборудования, которые закончились еще ДО даты начала анализа, их тоже включать? Зачем тогда вообще дата начала? Обычно, если есть какая-то сущность характеризующаяся временным интервалом, и некий период, то просят найти, все сущности, которые хоть как-то "зацепили" этот период. В том числе и тот случай, когда интервал полностью лежит в рассматриваемом периоде (который вы сказали вам особенно непонятен). Например, если период текущий месяц, то это случаи: а) взяли в прошлом месяце, отдали в текущем б) взяли в текущем месяце, отдали в текущем месяце в) взяли в текущем месяце, отдадут в будущем.
Если это то, что вы хотели описать, то чтобы выбрать такие записи, условие выглядит так:
...where DateEnd >= @PeriodStart or DateStart <= @PeriodEnd

Если нет, то мне непонятен смысл.
8 авг 12, 13:03    [12981043]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
MrBlackJack
Member

Откуда:
Сообщений: 43
SomewhereSomehow
а) взяли в прошлом месяце, отдали в текущем б) взяли в текущем месяце, отдали в текущем месяце в) взяли в текущем месяце, отдадут в будущем.
Если это то, что вы хотели описать, то чтобы выбрать такие записи, условие выглядит так:
...where DateEnd >= @PeriodStart or DateStart <= @PeriodEnd

Если нет, то мне непонятен смысл.

Да, частично это так, но есть еще несколько своеобразных условий, которые очень тяжело сформулировать)
Например,
1) Если взяли в прошлом или в текущем, отдали в текущем, но дата возврата меньше даты окончания анализ - не берем
2) Если взяли в прошлом или в текущем, отдали посреди текущего месяца, потом еще раз взяли в этом месяце (например пару дней оборудование было в ремонте на складе) ) - в таком случаи надо учитывать период до ремонта в текущем месяце, пару дней ремонта, и период после ремонта).
3) Если ситуация как в пункте 2, но после ремонта взяли, оно у них проработало несколько дней(неделю) и они вернули обратно...И если эта дата меньше даты окончания анализа(конец месяца) - то не берем ни одной строчки по этому оборудованию))
На самом деле задача очень специфичная, она решилась, пришлось рассмотреть очень много вариантов)...Я даже сейчас наверно плохо описал требования...
SomewhereSomehow,Mnior, спасибо Вам за оказанную помощь!
8 авг 12, 14:34    [12981906]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SomewhereSomehow,
1. DateEnd и DateStart берутся из представления
2. Ваш запрос приводит к полному сканированию.

MrBlackJack
3) Если ситуация как в пункте 2, но после ремонта взяли, оно у них проработало несколько дней(неделю) и они вернули обратно...И если эта дата меньше даты окончания анализа(конец месяца) - то не берем ни одной строчки по этому оборудованию))
Это почему?
Мне кажется вы усложняете задачу. Логически должно быть как показал SomewhereSomehow.
8 авг 12, 18:54    [12983984]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior
SomewhereSomehow,
1. DateEnd и DateStart берутся из представления
2. Ваш запрос приводит к полному сканированию.

1. Мне без разницы
2. Нет
8 авг 12, 20:53    [12984379]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SomewhereSomehow
Нет
Прям прёт.

Ну и почему по вашему нет?
9 авг 12, 09:20    [12985513]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior,

Потому, что проверьте сами. Сделайте таблицу, индексы по полям с датой и проверьте.

Правда в сам запрос закралась опечатался, должно быть либо так
not (DateEnd < @DateStart or DateStart > @DateEnd)

либо, в раскрытом виде так
c.DateEnd >= @DateStart and c.DateStart <= @DateEnd

Объяснение давал тут 11634216.
Я надеюсь вы это поняли, прежде чем говорить про скан? Или увидели or и сразу улю-лю скан?
9 авг 12, 10:02    [12985714]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SomewhereSomehow
Объяснение давал тут 11634216
А вы ту тему читали до конца?
SomewhereSomehow
Или увидели or и сразу улю-лю скан?
Вы знает, а я OR даже не увидел. Штампы восприятия.
Ну это не меняет дело.
9 авг 12, 11:19    [12986338]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior,
Тогда тем более странно.

if object_id('dbo.t1') is not null drop table t1;
create table t1(id int identity primary key, DateStart datetime, DateEnd datetime, c char(100) not null default '');
create index ix_ds on t1(DateStart);
create index ix_de on t1(DateEnd);

insert into t1(DateStart, DateEnd)
select
	dateadd(dd,number,'19900101'),
	dateadd(dd,number+10,'19900101')
from
	master..spt_values v1
where
	type = 'P'
;
go
set statistics xml on
go
declare @PeriodStart datetime='19900101', @PeriodEnd datetime = '19900110';
select * from t1
where DateEnd >= @PeriodStart and DateStart <= @PeriodEnd
option(recompile)
;
go
set statistics xml on
go
9 авг 12, 11:43    [12986527]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SomewhereSomehow,
Вы тему то читали? Чё вы по кругу теже вопросы подымаете. Лень читать?
У вас скан, посмотрите на оператор. Где в нём второе условие?
Ваш ReCompile помимо ненужной нагрузки на перекомпиляцию не защитит от скана в полтаблицы.
Лять, читайте ту тему, не надо тут Copy&Past-ом заниматься от лени. Ну на крайняк пишите туда.
9 авг 12, 11:50    [12986561]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior,

Мда...."скана в полтаблицы"! Вы вообще в курсе какие методы доступа бывают?
У вам идет поиск по индексу, после того как первое значение найдено, идет частичное сканирование индекса на предмет проверки второго условия. Где вы вообще увидели сканирование таблицы??? И почему такая странная оценка в половину?
9 авг 12, 12:05    [12986692]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SomewhereSomehow, вы придираетесь к словам. Но скана от этого меньше не станет.
Если в этом вся загвоздка (100% скан или 50%) и вы соглашаетесь что ваш запрос не эффективен. То я извиняюсь.

SomewhereSomehow
И почему такая странная оценка в половину?
Если @PeriodStart и @PeriodEnd будут попадать не середину таблы.
Лять, ну прочитайте ту тему. Боже мой.
9 авг 12, 13:36    [12987557]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SomewhereSomehow
Вы вообще в курсе какие методы доступа бывают?
Давайте не надо ляля.
Если почитаете внимательно то поймёте что здесь "изначально считать собеседника дураком" не прокатит.
9 авг 12, 13:41    [12987600]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior
SomewhereSomehow, вы придираетесь к словам. Но скана от этого меньше не станет.
Если в этом вся загвоздка (100% скан или 50%) и вы соглашаетесь что ваш запрос не эффективен. То я извиняюсь.

SomewhereSomehow
И почему такая странная оценка в половину?
Если @PeriodStart и @PeriodEnd будут попадать не середину таблы.
Лять, ну прочитайте ту тему. Боже мой.

Вы не нервничайте так =) И я не придираюсь. Вы сами в очередной раз сморозили. Типа "приводит к полному скану", не "может приводить", а "приводит"!, да еще и не индекса а таблицы. Безаппеляционно! Вы запускали пример? Видите там в плане index seek? В принципе, я могу больше ничего уже не объяснять т.к. это уже опровергает утверждение
Mnior
2. Ваш запрос приводит к полному сканированию.

Нет? Вы же гений доказательств и логики?
Именно по этому я сказал
SomewhereSomehow
2. Нет


А ваше утверждение что называется "it depends" - верно далеко не всегда и не везде, и потому что зависит от индексов (например добавьте еще один индекс и поиск будет в середине таблы, как вы выражаетесь) или распределения или параметров или фиг знает чего еще, не говоря уже о том что мы всего этого не знаем и вопрос такой не поднимался.
9 авг 12, 14:35    [12988058]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SomewhereSomehow, то что вас "прищючили" и хотите показать себя в хоть в чём-то "правым" и вы хотите цепляетесь к терминам - ваше право. С этим я не спорю.

SomewhereSomehow
Типа "приводит к полному скану", не "может приводить", а "приводит"!, да еще и не индекса а таблицы.
Да, приводит к сканированию. Ну какая к чёрту разница, индекса или таблицы. Это что меняет дело?
Но ваш вариант палюбе не эффективен. Ну можете быть иногда давать те же показатили - но это дело не меняет.

Но главное другое. Какая нафиг к чёрту разница если всё это замусолено в той теме. Зачем давать мне возможность ошибиться в терминах, вместо того чтобы прочитать ту тему и согласиться что ваше "нет" ошибочно.
Но вы продолжате писать в этой теме.

SomewhereSomehow
Вы запускали пример?
Ну вы и тормоз, естественно да, это же вы профтыкиваете в вопросе. Прочитайте же наконец ту тему. Убедитесь, что да, вы не учитали все нюансы.

SomewhereSomehow
Видите там в плане index seek?
И что? этот SEEK ничего не значит совершенно ничего, нужно учитывать ВСЁ, а не как вы, SomewhereSomehow, постоянно делаете только поверхностный анализ и поэтому часто ошибаетесь.
Или вы попытаетесь слится?

SomewhereSomehow
В принципе, я могу больше ничего уже не объяснять т.к. это уже опровергает утверждение
Mnior
2. Ваш запрос приводит к полному сканированию.
Вы троль, толстый такой троль. Я же написал что я неточно выразился. Да не к полному, но то точно излишнему скану.
Но продолжаете настаивать что ваш запрос "белый и пушистый". А почему он хреновый вы не хотите понять, вас больше интересует как отразить "нападки со стороны".

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

И вы опять будете писать сюда, а не в ту тему?
9 авг 12, 16:38    [12989209]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Ок. Аргументы вам до фени, ну тогда будем давить авторитетом (обычно на гуманитариев это действует). Цитирую:
locky
Да как ни крути при поиске пересекающихся периодов или по одной или по другой дате будет слишком объемный скан индекса
Да, мы ограничиваем ренж скана (больше или меньше определённой даты), но в общем случае у нас под условие попадает половина таблицы. Это как бы плохо.
Хочется идеального индекса.
9 авг 12, 16:42    [12989247]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior,

Во первых, хватит вопить "прочитайте-прочитайте", я ее читал и даже участвовал (а сейчас еще раз перечитал).
Во-вторых запрос я белым пушистым не называл. Я возражал что он всегда приводит к скану. Не занимайтесь приписками слов.
В-третьих, я как раз учитываю все случаи, по этому и могу говорить что он всегда приводит к скану. Вы - нет.
В-четвертых, вы реально не понимаете что такое частичный просмотр, а также не отличаете скана индекса и скана таблицы.
И, наконец в-пятых, пройдтесь тут, закрепите навык =)
Хотел вам еще пример привести с разными хинтами, но не буду, хреновый вы спорщик какой-то сразу кричите и пытаетесь оскорбить, зачем? никакого конструктива и никакого понимания сути происходящего, никаких примеров, сплошная демагогия, тьху...
9 авг 12, 16:58    [12989361]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
+ SomewhereSomehow
SomewhereSomehow
Во первых, хватит вопить "прочитайте-прочитайте", я ее читал и даже участвовал (а сейчас еще раз перечитал).
Совершенно не видно что вы участвовали. А если бы прочитали изначально то не настаивали что вас запрос эффективен.
SomewhereSomehow
Я возражал что он всегда приводит к скану.
Если вы имеете ввиду, что оно не всегда приводит к существенному скану. Да без проблем. Только всё это совершенно не важно. Всегда хреново или нет. Не в этом основной то вопрос стоит. Если уже есть гарантированное нормальное решение, чё мусолить.
SomewhereSomehow
В-третьих, я как раз учитываю все случаи, по этому и могу говорить что он всегда приводит к скану. Вы - нет.
Не понял.
SomewhereSomehow
В-четвертых, вы реально не понимаете что такое частичный просмотр, а также не отличаете скана индекса и скана таблицы.
Я вас умоляю, ну не надо вот этого ля-ля на ровном месте. Вам что искать все мои посты N летней давности где видно обратное? Хватит тролить.
SomewhereSomehow
И, наконец в-пятых, пройдтесь тут, закрепите навык =)
Вы в туже степь. У вас всё делится по эмоциям, если некоторые слова подходит под набор, так всё - демагогия. Демагог вы тут, когда эмоционально тут реагируете минуя смысл сказаного.
Я прекрасно понимаю таких людей, если им не комфортно они сразу голову в песок. Им совершенно до лампочки точность своих рассуждений - комфорт важнее точности понимания.
И главное они боятся это признать, а некоторые готовы согласиться "для виду" лишь бы закрыть тему в состоянии "недосказанности". Таких тьма.
SomewhereSomehow
Хотел вам еще пример привести с разными хинтами, но не буду
Естественно, их вы не сможете привести. Вы только обвиняете без аргументов. Как обычно. Увеличивая свой "вес".
Вам не нраится так многа букав. Так и напишите.
SomewhereSomehow
хреновый вы спорщик
Да, факты кому-то могут не нравиться, и это кого-то обижает когда их выявляют. Если это для вас "хреновый", пжалуста, можете так называть, мне пофигу.
SomewhereSomehow
какой-то сразу кричите и пытаетесь оскорбить, зачем?
Это где оскорбить? Факты оскорбляют только неадекватов.
SomewhereSomehow
никаких примеров, сплошная демагогия
Ну вы можете попытаться измениться.
Попытайтесь обращать внимание на смысл и тему обсуждения в первую очередь.
Если вы хотите можно закрыть глаза на всё выше сказанное и продолжить отседова: 12985513.
С уточнением:
where DateEnd >= @PeriodStart and DateStart <= @PeriodEnd
Является не эффективным / не надёжным и хуже чем приведённый выше.

И кстати да, в той теме был вариант когда схема данных не позволяла поставить нормальное условие.
И коль уж так привожу ещё тему, так для связанности.
9 авг 12, 20:40    [12990284]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior,

По ссылке сюда почему там фигурирует одно поле дата? Вы пожалуйста полностью приведите решение для интервалов, а не то что вам видится. Далее - сравним! Домысливать что вы там "имели ввиду" - это я так понял приемчик таких как вы (отражено в моей ссылке). Которым вы воспользовались ранее. Вы вместо этого, предоставьте нормальный тест.

Почему вы убрали под кат свое поражение?
Mnior
Если вы имеете ввиду, что оно не всегда приводит к существенному скану. Да без проблем. Только всё это совершенно не важно. Всегда хреново или нет. Не в этом основной то вопрос стоит. Если уже есть гарантированное нормальное решение, чё мусолить.

Вот вам реальный кейс. Есть система учета звонков. Звонки фиксируются как дата начала, завершения и код интервьюера. Таблица копится за несколько лет, но для оперативных нужд контроля супервизорами за интервьюерами предусмотрено - делать выборку рандомного интервала в пределах последнего месяца, который укажет супервизор, на тему, какие были звонки. И вы знаете! Смотрю в процедуру и вижу seek! Всегда! Что поделать? Согласно Mnior надо оптимизировать запрос для "универсальной" выборки?! Даже если ее никогда не будет, потому что бизнес логика предполагает начисление премий только за текущий месяц.

"что он всегда приводит к скану." - это просто опечатка я пропустил "не" - "не всегда".
Остальное, что вы называете "фактами" - например причисление меня к тормозам, даж комментировать не охота, настолько беспомощно это выглядит =)

Теперь, я вижу что вы конкретно не понимаете причин. В последний раз пробую объяснить.
Да, есть проблема, проблема в том, что при оценке оптимизатор руководствуясь гистограммой считает сколько строк ему надо просмотреть, а проблема, в том, что оптимизатор не имеет многомерных гистограмм! Т.е. он оценивает кол-во строк для первой колонки, так, как если бы индекс был только по ней, и разумеется с определенного значения он может(!!!), но не обязательно (см. кейс выше) свалиться в скан таблицы. Но и в этом случае, делая составной индекс по колонкам даты, и используя подсказку по индексу, мы можем заставить оптимизатор использовать поиск по индексу и частичный просмотр, если знаем что данные буду распределены более-менее равномерно!
А вот вам данные в "середине таблы"?
+
if object_id('dbo.t1') is not null drop table t1;
create table t1(id int identity primary key, DateStart datetime, DateEnd datetime, c char(2000) not null default '');
--create index ix_ds on t1(DateStart);
--create index ix_de on t1(DateEnd);
create index ix_dsde on t1(DateStart,DateEnd); --допустим только этот индекс
--create index ix_deds on t1(DateEnd,DateStart);

insert into t1(DateStart, DateEnd)
select
	dateadd(dd,number,'19900101'),
	dateadd(dd,number+10,'19900101')
from
	master..spt_values v1
where
	type = 'P'
;
go
dbcc dropcleanbuffers;
go
set statistics xml,time, io on
go
--declare @PeriodStart datetime='19900101', @PeriodEnd datetime = '19900110';
declare @PeriodStart datetime='19920110', @PeriodEnd datetime = '19920110';
select * from t1 
with(index(ix_dsde))
where DateEnd >= @PeriodStart and DateStart <= @PeriodEnd
option(recompile)
;
go
set statistics xml,time, io off
go
dbcc dropcleanbuffers;
go
set statistics xml,time, io on
go
declare @PeriodStart datetime='19920110', @PeriodEnd datetime = '19920110';
select * from t1 
where DateEnd >= @PeriodStart and DateStart <= @PeriodEnd
option(recompile)
;
go
set statistics xml,time, io off
go
drop table t1;

Результат
автор
Таблица "t1". Число просмотров 1, логических чтений 51, физических чтений 0, упреждающих чтений 0, lob логических чтений 0, lob физических чтений 0, lob упреждающих чтений 0.
Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 34 мс.

Таблица "t1". Число просмотров 1, логических чтений 687, физических чтений 11, упреждающих чтений 653, lob логических чтений 0, lob физических чтений 0, lob упреждающих чтений 0.
Время работы SQL Server:
Время ЦП = 0 мс, затраченное время = 283 мс.

Запускал тест несколько раз. Всегда выигрывал вариант с хинтом.
Это к тому, что если вы знаете поднаготную, знаете распределение, знаете ваш запрос - то может быть стоит подсказать оптимизатору?
У вас в "голове" сработал нехитрый триггер: я знаю ситуацию когда это полохо -> Я не пробовал ее обойти -> Я не рассматривал ситуации когда это вообще не встретится -> но SomewhereSomehow посмел возразить! -> Я напишу что это плохо, потому что когда то рассматривал сферического коня в вакууме и (тут как раз возвращаемся к гуманитариям и авторитетам) авторитеты сказали что это всегда плохо -> ... -> PROFFIT!!!
Хватит уже. Я не уверую в вашу "теорию" хотя бы потому что имею перед глазами живой пример. И не думаю, что это какое-то сильное исключение.
9 авг 12, 21:34    [12990406]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Mnior,

А..! И да! Я знал, что это с вашей стороны, это опять не закончится ничем, кроме как говнометанием, поэтому, сначала отвечал лаконично, и если б вы не смущали умы новичков своими идиотскими безаппеляционными заявлениями - не ответил бы вообще. Впредь думаю не повторять своих ошибок, хотя бы потому что с вами просто неприятно вести диалог. Откуда весь этот пафос и самодержавие? Сказали бы просто, что "я знаю случаи, когда это может привести к неоптимальному плану" или "на моей практике такой запрос не эффективен, а эффективен такой...", я бы и спорить не стал. Сильно видать вас зацепило в очередной раз, гений логики =)
9 авг 12, 21:54    [12990471]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
Леша777
Guest
SomewhereSomehow, извините что я вмешиваюсь.

Тут же ведь проблема не в том, сваливается в скан запрос или нет. Проблема в том что для предиката вида
DateStart <= @PeriodEnd SEEK работает аналогично скану. Т.е читаются все страницы индекса начиная самых левых с мининимальным DateStart, пока не встретим страницу DateStart > @PeriodEnd.

Т.е чем больше @PeriodEnd тем больше сканируем.
Это очень хорошо видно на следующем примере, используя вашу таблицу лишь выкинув обращение к кластерному индексу.


SET STATISTICS IO ON;
SET NOCOUNT ON;
-- 90ый год 
SELECT  t.DateStart, t.DateEnd
FROM dbo.t1 as t 
WHERE t.DateEnd >= '1990-01-01' and t.DateStart <= '1990-01-01' ;

-- 92ой год  ~середина 
SELECT  t.DateStart, t.DateEnd
FROM dbo.t1 as t 
WHERE t.DateEnd >= '1992-01-01' and t.DateStart <= '1992-01-01' ;

-- 95 ый год ближе к концу 
SELECT  t.DateStart, t.DateEnd
FROM dbo.t1 as t 
WHERE t.DateEnd >= '1995-01-01' and t.DateStart <= '1995-01-01' 

-- полный скан 
SELECT  t.DateStart, t.DateEnd
FROM dbo.t1 as t
 


Мои результаты :


Table 't1'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 't1'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 't1'. Scan count 1, logical reads 8, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 't1'. Scan count 1, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.


Данные то для любой выборки хранятся то, на одной единственной странице. А мы в зависимости от параметра читаем больше и больше страниц.
В плане запроса да - SEEK, но работат он как скан.
9 авг 12, 23:28    [12990778]     Ответить | Цитировать Сообщить модератору
 Re: Учет движения  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Леша777,

В том то и дело, что не работает как скан. Во первых, вы что-то тут напутали
"DateStart <= @PeriodEnd SEEK работает аналогично скану. Т.е читаются все страницы индекса начиная самых левых с мининимальным DateStart, пока не встретим страницу DateStart > @PeriodEnd."
Видимо опечатка, следует читать как
"DateStart <= @PeriodEnd SEEK работает аналогично скану. Т.е читаются все страницы индекса начиная самых левых с мининимальным DateStart, пока не встретим страницу DateEnd >= @PeriodStart."
Теперь, по сути.
То что не понимает мой оппонент Mnior. index scan <> clustered or table scan. - т.к. индкс у'же. Меньше страниц. Во вторых, следует различать что тут нет никакой особенной ситуации. Представьте - индекс по полую "а" и условие "а<10" - 10 строк, а теперь "а>10", 1000000 строк, например. Есть ведь разница? Когда оптимизатор оценивает план, он смотрит на гистограмму статистики и значения и оценивает, "а сколько согласно условию строк я получу", суммируя все значения количества в гистограмме больше заданного, по этому, разумеется это зависит от переданного значения!

Далее, в этом смысле, нет никаких отличий от того, что Izik Ben Gan называет selectivity point, т.е. точки когда поиск+просмотр становится менее выгодным чем сканирование. Селективность ли это ключа который на 1 значение имеет 10 строк или 10 ключей, которые имеют по сроке каждый. В статистике это отражается как 10 строк (что и есть по сути в таблице).
По этому, чем больше значение одного параметра и меньше значение другого, чем больше расширяется интервал, тем больше затрагивается строк, и тем невыгоднее оптимизатору потом делать по ним поиск. Это все полностью аналогично любым рассуждениям о селективности.

Теперь, вы сравните в своем примере предполагаемое и фактическое число строк, и вы поймете, что оптимизатор, к сожалению, делает оценки исходя из гистограммы первого столбца. У него нет многомерных гистограмм. Но фактическое число строк - расставляет все по своим местам. Таким образом, повторяю, зная свои реальные данные и распределение, а также запросы - можно побороться за оценки и выиграть.

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

И запомните пожалуйста, как бы ни смущали вас иные личности, что partial index scan <> table scan!
При определенных условиях будет только partial scan. А если вы уверены, что вам выгоднее всегда именно он, то можно и помочь хинтом (хотя я с таким не сталкивался на практике)!
10 авг 12, 00:11    [12990901]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить