DG>>т.е. в С# нет единой функции идентичности? S>Нет, но ее легко определить.
определи, пожалуйста, раз это легко сделать.
DG>>и соответственно, C# не является ООП-языком, т.к. ранее тот же Sinclair утверждан, что в ООП функция идентичности должна быть одна. S>Вот тут немного непонятно. Что будет если функций будет 10 и все они будут давать одинаковый результат?
тогда это одна и та же функция, только записанная десять раз.
S>Я вообще не понимаю, о чем речь. Идентичность в C# определена через storage location, для проверки идентичености используется Object.ReferenceEquals (по определению идентичностии ECMA). Соответсвенно, объекты разных типов не могут быть друг другу идентичны. null любого типа идентичен любому другому null.
кстати, мне кажется, что ты мне баки заливаешь — подменяя индентичность объектов на индентичность ссылок.
Identity allows comparison of references. Two references can be compared whether they are equal or not. Due to the identity property, this comparison has special properties. If the comparison of references indicates that the references are equal, then it's clear that the two objects pointed by the references are the same object. If the references do not compare equal, then it's not necessarily guaranteed that the identity of the objects behind those references is different. The object identity of two objects of the same type is the same, if every change to either object is also a change to the other object.
object.ReferenceEquals не удовлетворяет выделенному, соответственно она не является функции идентичности в ООП-понимании
Здравствуйте, DarkGray, Вы писали:
DG>>>каким же образом? и является ли при этом это отношением транзитивным? S>>Побитовым сравнением. Да, транзитивность выполняется.
DG>я правильно, что ты утверждаешь, что struct{int x} идентично struct{float x}?
ECMA-335 8.2.5.1 Identity
The identity operator is defined by the CTS as follows.
• If the values have different exact types, then they are not identical.
• Otherwise, if their exact type is a value type, then they are identical if and only if the bit
sequences of the values are the same, bit by bit.
• Otherwise, if their exact type is a reference type, then they are identical if and only if the
locations of the values are the same.
Identity is implemented on System.Object via the ReferenceEquals method.
DG>>>т.е. в С# нет единой функции идентичности? S>>Нет, но ее легко определить.
DG>определи, пожалуйста, раз это легко сделать.
Пардон, с наскоку не получилось сравнить структуры побитово.
DG>>>и соответственно, C# не является ООП-языком, т.к. ранее тот же Sinclair утверждан, что в ООП функция идентичности должна быть одна. S>>Вот тут немного непонятно. Что будет если функций будет 10 и все они будут давать одинаковый результат?
DG>тогда это одна и та же функция, только записанная десять раз.
Здравствуйте, DarkGray, Вы писали:
S>>Я вообще не понимаю, о чем речь. Идентичность в C# определена через storage location, для проверки идентичености используется Object.ReferenceEquals (по определению идентичностии ECMA). Соответсвенно, объекты разных типов не могут быть друг другу идентичны. null любого типа идентичен любому другому null.
DG>кстати, мне кажется, что ты мне баки заливаешь — подменяя индентичность объектов на индентичность ссылок.
С этим к ECMA.
DG>http://en.wikipedia.org/wiki/Identity_(object-oriented_programming)
DG>
DG>Identity allows comparison of references. Two references can be compared whether they are equal or not. Due to the identity property, this comparison has special properties. If the comparison of references indicates that the references are equal, then it's clear that the two objects pointed by the references are the same object. If the references do not compare equal, then it's not necessarily guaranteed that the identity of the objects behind those references is different. The object identity of two objects of the same type is the same, if every change to either object is also a change to the other object.
DG>object.ReferenceEquals не удовлетворяет выделенному, соответственно она не является функции идентичности в ООП-понимании
А можно продемонстрировать как нарушается выделенное?
DG>> The object identity of two objects of the same type is the same, if every change to either object is also a change to the other object.
DG>>object.ReferenceEquals не удовлетворяет выделенному, соответственно она не является функции идентичности в ООП-понимании S>А можно продемонстрировать как нарушается выделенное?
нарушается, уже банально на строках:
string y = "2";
Console.WriteLine(Object.ReferenceEquals(y, y));
Console.WriteLine(Object.ReferenceEquals(y + "1", y + "1"));
выдает
True
False
после применения одного и того же изменения, идентичные объекты перестали быть идентичными.
DG>>> The object identity of two objects of the same type is the same, if every change to either object is also a change to the other object.
DG>>>object.ReferenceEquals не удовлетворяет выделенному, соответственно она не является функции идентичности в ООП-понимании S>>А можно продемонстрировать как нарушается выделенное?
DG>нарушается, уже банально на строках: DG>
DG> string y = "2";
DG> Console.WriteLine(Object.ReferenceEquals(y, y));
DG> Console.WriteLine(Object.ReferenceEquals(y + "1", y + "1"));
DG>
DG>выдает DG>
DG>True
DG>False
DG>
DG>после применения одного и того же изменения, идентичные объекты перестали быть идентичными.
Здесь ничто не изменилось
DG>>>> The object identity of two objects of the same type is the same, if every change to either object is also a change to the other object.
DG>>после применения одного и того же изменения, идентичные объекты перестали быть идентичными. S>Здесь ничто не изменилось
как только в выделенном найдешь (или в другом месте текста про identity), что change объекта не имеет права создавать новые копии объекта, тогда продолжим разговор.
DG>>>>> The object identity of two objects of the same type is the same, if every change to either object is also a change to the other object.
DG>>>после применения одного и того же изменения, идентичные объекты перестали быть идентичными. S>>Здесь ничто не изменилось
DG>как только в выделенном найдешь (или в другом месте текста про identity), что change объекта не имеет права создавать новые копии объекта, тогда продолжим разговор.
В выделенном не об этом. Где-нибудь в другом месте текста про identity по той ссылке тоже об этом нет. Ну а кроме этого, в твоем примере нет и намека на попытку изменения объекта.
Здравствуйте, vdimas, Вы писали:
V>А не преподавали "четкого разделения слоев". И самостоятельно в учебниках не видел.
А вот нам как раз преподавали. У меня просто профильная специальность никакого отношения к программированию не имеет.
А на квантовой оптике обучают математике и физике, и чётко проводят границы между моделями.
V>И ты пока тоже ничего не сформулировал. И под вопросом вообще разделение слоев абстракций, бо в классике абстракции — это градиент, коль не задано обратное, где на одном из полюсов используется минимум деталей, а на другом максимум.
Ну откуда же может взяться градиент в заведомо дискретном множестве?
V>Нет никаких слоев, заданных свыше. "Слои абстракций" бывают в рамках конкретного проекта/продукта, и они могут выбираться на усмотрение разработчиков.
Конечно. Тем не менее, границы между слоями (в приличной архитектуре) чётко выражены.
ограничений на этот счет нет. Назначение этой абстракции ровно одно — объяснять суть происходящего, опуская несущественные детали. А ты почему-то решил, что абстракции нужны исключительно для сокрытия деталей.
Нет, я так не решил.
V>Ладно. Плохой признак, когда к профайлеру приходится часто обращаться.
Конечно плохой — это означает, что вы профилируете невовремя, т.е. занимаетесь premature optimization.
Я, кстати, под профайлером в данном контексте понимаю не конкретное приложение, а вообще измерение производительности — это чтобы избежать ненужных споров. Я полностью согласен с вашей критикой профайлеров и с тем, что специальным образом проведённые тесты — это круто и правильно.
А вот с тем, что умственное моделирование производительности лучше, чем измерение, я не соглашусь.
V>Мде? ну я бы не стал этим хвастаться. У меня в 100% случаев первоначальные предположения совпадают как с с данными профайлера, так и с разницей тестов на производительности...
Искренне завидую. Жаль, что таких людей в природе больше нет. V>Приемов-то оптимизации не так много в природе, овладел ими еще в прошлом веке. И обратное тоже верно — потенциальных типов узких мест (грубо говоря — антипаттернов) очень мало в природе. И они сразу бросаются в глаза. Профалер тут хорош лишь в деле расстановки приоритетов перед началом зачистки этого мусора и то, весьма приблизительно. Бо в конкретном некоем сценарии профалер покажет одну частоту вызовов "узких мест" (например, маленькую), а реально она может вызываться чуть чаще... Поэтому когда речь идет всерьез, то собирается статистика в логах прямо из "боевого" применения, где ни о каких профайлерах речи быть не может...
Можете продемонстрировать на простом примере? Вот в этой несложной программе, где именно боттлнек (чур, профайлер не запускать):
public static void Main()
{
while (true)
{
Console.Write("Enter rack (use '?' for blank): ");
string rack = Console.ReadLine();
if (rack == "")
break;
Console.WriteLine("{0} : {1}", rack, SearchDictionary(rack).Join());
foreach (char c in"ABCDEFGHIJKLMNOPQRSTUVWXYZ")
Console.WriteLine("{0}+{1} : {2}", rack, c, SearchDictionary(rack + c).Join());
}
}
private static string Join(this IEnumerable<string> strs)
{
return string.Join(" ", strs.ToArray());
}
private static string Canonicalize(string s)
{
char[] chars = s.ToUpperInvariant().ToCharArray();
Array.Sort(chars);
return new string(chars);
}
private static IEnumerable<string> SearchDictionary(string originalRack)
{
const string dictionary = @"d:\twl06.txt";
// Calculate all the possible distinct values for the rack.
// As an optimization, stuff the resulting racks in an array so
// that we do not recalculate them during the query. var racks = (from rack in ReplaceQuestionMarks(originalRack)
select Canonicalize(rack)).Distinct().ToArray();
// Check every line in the dictionary to see if it matches
// any possible rack. As an optimization, do an early
// out if the line length does not match the query length. return from line in FileLines(dictionary)
where line.Length == originalRack.Length
where racks.Contains(Canonicalize(line))
select line;
}
private static IEnumerable<string> ReplaceQuestionMarks(string s)
{
int index = s.IndexOf('?');
if (index == -1)
{
yield return s;
yield break;
}
foreach (char c in"ABCDEFGHIJKLMNOPQRSTUVWXYZ")
{
string s2 = s.Substring(0, index) + c.ToString() + s.Substring(index + 1);
foreach (string result in ReplaceQuestionMarks(s2))
yield return result;
}
}
private static IEnumerable<string> FileLines(string filename)
{
using (var sr = File.OpenText(filename))
{
while (true)
{
string line = sr.ReadLine();
if (line == null)
yield break;
yield return line;
}
}
}
Это программа для игры в скрэббл. Она грузит примерно двухмегабайтный файл со словарём английских слов (путь к файлу захардкожен) и выполняет поиск слова, которое можно собрать из заданных ей на входе букв (нужно использовать все предоставленные буквы).
Она чудовищно неоптимальна. V>Наверно, потому что в первую очередь при поднятии производительности умудряюсь множество shared-сценариев свести к local...
Это замечательно. V>Потому что этот уровень настолько далеко отстоит в сравнении с затратами на создание делегата и глобальной блокировкой общего мьютекса на все потоки... что это будет явная профанация, рядом с дотнетными замыканиями обсуждать такие вещи. Просто ты ведь не в курсе, наверно, про эту общую для всех потоков блокировку при создании экземпляра делегата, помимо собственно затратной операции создания делегата, отсюда неуместные рассуждения о приемах, которые на несколько порядков дают меньший прирост, чем простое избавление от делегата... (хоть они тоже в ходу в кач-ве приемов оптимизации.. но уже на совсем другой итерации работ по оптимизации, даже не второй и не третьей)... ИМХО, отсюда и 90% твоих ошибок в первоначальных предположениях. Можно продолжать игнорировать тонкости реализации и дальше.
Не, я не в курсе про эту общую для всех потоков блокировку. А где можно про неё прочитать? Уж очень фантастически звучит.
V>У меня нет границ вообще.
Это я вижу.
V>Про индексы речь шла в деле понимания плана запросов. А сам план запросов как раз в терминах реляционной алгебры отображается.
Неужели? Ну, значит, моё понимание РА сильно отстало от жизни. Когда я в последний раз к ней обращался, там не было никаких Bookmark Lookup, Table Rewind, Clustered Index Seek и прочего.
V>И да, когда изучают реляционную алгебру, то непременно проходят операцию "проекция", сохранением результата которой и является индекс в классике.
Простите, но это чушь. То, что получается в результате выполнения проекции, даже если его сохранить, никак не может быть индексом в классике. Если вам очень хочется поспорить про это — попробуйте применить такой "индекс" для оптимизации какого-нибудь запроса.
Скажем, вот у нас табличка
create table person(id int identity primary key, name varchar(max) not null, gender char(1) not null, picture )
Мы хотим оптимизировать запрос
select id from person where name = 'vdimas'
Расскажите мне, результат какой операции "проекция" тут поможет так же, как
create index ByName on person(name, id)
V>Так не стоит упускать из виду, что реляционная алгебра существует не сама по себе, а как инструмент над реляционной моделью, т.е. другие свои характеристики, например уникальность/неуникальность, индексы берут из раздела реляционной модели данных, которая, анпример, оперирует понятиями основного и альтернативных ключей. И да, понятие индекса идет вместе с реляционными базами данных, для которых, собственно, и была разработана реляционная модель.
Бррр. Опять каша. Реляционная алгебра — это раздел математики, достаточно строго определённый. Она работает с реляциями.
V>Несвязный набор слов. Одно использует другое. SQL оперирует терминами реляционного исчисления, но стоимость операций реляционного исчисления недетерминирована.
Это у вас несвязный набор слов. SQL отклоняется от реляционной алгебры, т.к. представляет компромисс между математической строгостью и вопросами реальной производительности. Терминами реляционного исчисления SQL никак не оперирует:
The current ISO SQL standard doesn't mention the relational model or use relational terms or concepts.
(http://en.wikipedia.org/wiki/Relational_model)
Вопросы стоимости операций появляются только в тот момент, когда мы заменяем абстрактные операции расширенной РА в логическом плане запроса конкретными операциями физического плана запроса. Именно в этот момент появляется простор для оптимизаций, т.к. одному и тому же логическому плану запроса может соответствовать много различных физических планов запроса, отличающихся стоимостью.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
DG>>как только в выделенном найдешь (или в другом месте текста про identity), что change объекта не имеет права создавать новые копии объекта, тогда продолжим разговор. S>В выделенном не об этом. Где-нибудь в другом месте текста про identity по той ссылке тоже об этом нет. S> Ну а кроме этого, в твоем примере нет и намека на попытку изменения объекта.
это не формально. введи формальное определение в виде: изменение называется ..., а данная операция этому определению не удовлетворяет.
зы
более сложный пример на тоже самое. есть два объекта y, z, потом они меняются на одно и тоже — и становятся не одинаковыми
string y = "2";
string z = y;
Console.WriteLine(Object.ReferenceEquals(z, y));
y += "1";
z += "1";
Console.WriteLine(Object.ReferenceEquals(z, y));
Здравствуйте, samius, Вы писали:
S>Алгоритм есть, переменные есть (если с их помощью описан алгоритм). А то что после суперкомпиляции не осталось переменных — как раз и подтверждает ту точку зрения что делать выводы о сущностях программы по сущностям времени выполнения наивно.
Да не наивно ни разу. Конечный результат все-равно получен ч помощью заданной нами семантике. А какие уж там преобразования сделает суперкомпилятор — это темный лес. Тем более, что для поданной константы он сделает эти преобразования, а для данных времени исполнения — фиг там... Вот и вернулись к начальной точке.
DG>>>как только в выделенном найдешь (или в другом месте текста про identity), что change объекта не имеет права создавать новые копии объекта, тогда продолжим разговор. S>>В выделенном не об этом. Где-нибудь в другом месте текста про identity по той ссылке тоже об этом нет. S>> Ну а кроме этого, в твоем примере нет и намека на попытку изменения объекта.
DG>это не формально. введи формальное определение в виде: изменение называется ..., а данная операция этому определению не удовлетворяет.
Какая операция? Какому определению?
DG>зы DG>более сложный пример на тоже самое. есть два объекта y, z,
Объект один. И первый ReferenceEquals указывает на это.
DG>потом они меняются на одно и тоже — и становятся не одинаковыми
Объект не меняется, меняются ссылки. DG>
DG> string y = "2";
DG> string z = y;
DG> Console.WriteLine(Object.ReferenceEquals(z, y));
DG> y += "1";
DG> z += "1";
DG> Console.WriteLine(Object.ReferenceEquals(z, y));
DG>
После изменения значений переменных, ссылки, которые в них хранятся, больше не указывают на один и тот же объект.
Что ты пытаешься опровергнуть этим примером? Что RefEquals не может выступать в роли критерия идентичности?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>Алгоритм есть, переменные есть (если с их помощью описан алгоритм). А то что после суперкомпиляции не осталось переменных — как раз и подтверждает ту точку зрения что делать выводы о сущностях программы по сущностям времени выполнения наивно.
V>Да не наивно ни разу. Конечный результат все-равно получен ч помощью заданной нами семантике.
Результат работы программы — да. V>А какие уж там преобразования сделает суперкомпилятор — это темный лес.
Именно поэтому я и настаиваю на том, что результат компиляции не является основой для выводов о сущностях программы. V>Тем более, что для поданной константы он сделает эти преобразования, а для данных времени исполнения — фиг там... Вот и вернулись к начальной точке.
Даже для константы компилятор преобразования может сделать, а может и нет (может зависеть от параметров компиляции). Для времени исполнения — тоже не фиг там. Компилятор обязан обеспечить результат работы программы, но не сохранность сущностей ЯВУ.
Здравствуйте, Sinclair, Вы писали:
V>>Нет никаких слоев, заданных свыше. "Слои абстракций" бывают в рамках конкретного проекта/продукта, и они могут выбираться на усмотрение разработчиков. S>Конечно. Тем не менее, границы между слоями (в приличной архитектуре) чётко выражены.
Да, но не заданы свыше. Это принципиально.
S>ограничений на этот счет нет. Назначение этой абстракции ровно одно — объяснять суть происходящего, опуская несущественные детали. А ты почему-то решил, что абстракции нужны исключительно для сокрытия деталей. S>Нет, я так не решил.
V>>Ладно. Плохой признак, когда к профайлеру приходится часто обращаться. S>Конечно плохой — это означает, что вы профилируете невовремя, т.е. занимаетесь premature optimization. S>Я, кстати, под профайлером в данном контексте понимаю не конкретное приложение, а вообще измерение производительности — это чтобы избежать ненужных споров. Я полностью согласен с вашей критикой профайлеров и с тем, что специальным образом проведённые тесты — это круто и правильно. S>А вот с тем, что умственное моделирование производительности лучше, чем измерение, я не соглашусь.
Ну таки при некотором навыке экономит невообразимую массу времени во время разработки. И во время поиска узких мест у коллег тоже. Там не rocket-science вовсе... ты же обратил внимание, что мне сам факт обсуждения подобных вещей кажется странным? Это же обсуждение самой необходимости быть специалистом своего дела, или забить по принципу "и так сойдет"...
V>>Мде? ну я бы не стал этим хвастаться. У меня в 100% случаев первоначальные предположения совпадают как с с данными профайлера, так и с разницей тестов на производительности... S>Искренне завидую. Жаль, что таких людей в природе больше нет.
Есть — коллеги. Смотрел на сделанные ими преобразования недавно в критичном общем коде... я бы сделал один-в-один с точностью до несущественных подробностей. Могу лишь предположить, что тебе по работе всё, что мы тут обсуждаем, банально не очень нужно. А у нас она из этого состоит процентов на 90% или больше. Отсюда соответственные привычки и навыки.
V>>Приемов-то оптимизации не так много в природе, овладел ими еще в прошлом веке. И обратное тоже верно — потенциальных типов узких мест (грубо говоря — антипаттернов) очень мало в природе. И они сразу бросаются в глаза. Профалер тут хорош лишь в деле расстановки приоритетов перед началом зачистки этого мусора и то, весьма приблизительно. Бо в конкретном некоем сценарии профалер покажет одну частоту вызовов "узких мест" (например, маленькую), а реально она может вызываться чуть чаще... Поэтому когда речь идет всерьез, то собирается статистика в логах прямо из "боевого" применения, где ни о каких профайлерах речи быть не может... S>Можете продемонстрировать на простом примере? Вот в этой несложной программе, где именно боттлнек (чур, профайлер не запускать):
S>Это программа для игры в скрэббл. Она грузит примерно двухмегабайтный файл со словарём английских слов (путь к файлу захардкожен) и выполняет поиск слова, которое можно собрать из заданных ей на входе букв (нужно использовать все предоставленные буквы). S>Она чудовищно неоптимальна.
Скажу так, что ПЕРЕД началом оптимизаций, программу необходимо переписать. Например, читать из файла лишь однажды, прочитанные строки отсортировать по длине, а вместо генерации всех вариантов ReplaceQuestionMarks написать алгоритм непосредственного сравнения паттернов с "??". Т.е. для начала сделать преобразования алгоритмов в терминах O(n). И только после доработки алгоритмов можно приступать шлифовать коэффициент K при O(n). Это общая практика. Конечно, под "шлифовкой" алгоритмов я имею ввиду шлифовку технической части, а не самантической, т.е. не подмену самого алгоритма. Поиск удачных алгоритмов всегда гут, этот момент вроде бы даже тут разногласий не вызывает, правильно? Просто удачность алгоритма зависит от характера данных, например подаются данные по однму элементу, пачками или как еще. Иногда бывает так, что коэф при O(n) всяко важнее самого O(n) коль имеем тяжелые затраты на вызов, как в случае создания делегатов в дотнете в цикле или глубоких потенциальных вложенных енумераторов, как в твоем примере в злосчастном ReplaceQuestionMarks. Т.е. оптимизировать я бы взялся не эту, а преобразованную программу. Как и сказал выше, профайлер тут нужен для того, чтобы выяснить приоритет, какое из этих двух преобразований стоит сделать первым. Ну и опять же, надо понимать, что происходит даже в случае использования профайлера, т.е. заранее видеть потенциальное узкое место. Чтобы наткнуться на ReplaceQuestionMarks надо подать достаточно длинное слово со многими ??. Подай туда слово из трех букв — и ты ведь ничего не заметишь, какой бы волшебный профайлер не был.
S>Не, я не в курсе про эту общую для всех потоков блокировку. А где можно про неё прочитать? Уж очень фантастически звучит.
Это можно в тестах выяснить, зачем что читать? Как раз тонкости реализаций не всегда описаны. Берем 2 независимые от вызовов операции, одинаковые по стоимости в случае одного потока. Затем прогоняем их на многопроцессорной машине из многих потоков, строим график и видим, какая операция масштабируется фактически линейно, а какая нет.
V>>Про индексы речь шла в деле понимания плана запросов. А сам план запросов как раз в терминах реляционной алгебры отображается. S>Неужели? Ну, значит, моё понимание РА сильно отстало от жизни. Когда я в последний раз к ней обращался, там не было никаких Bookmark Lookup, Table Rewind, Clustered Index Seek и прочего.
А ты понял значение этих терминов? Bookmark Lookup — это восстановление соответствия м/у выделенным индексом и индексируемыми строками. Откуда берутся индексы — уже говорил выше. Clustered Index Seek — это есть операция "выборка" по проекции или "ограничение". "Clustered" — это подробность хранения индекса, идет из раздела реляционных баз данных. Я уже упоминал, что реляционные базы, реляционная модель, реляционное исчисление и реляционная алгебра связаны друг с другом. Матаппарат делиться на разделы, ок, ну разделы и разделы себе... Но использовать одно без другого бессмысленно, ведь реляционная модель была придумана для реляционных баз, а реляционное исчисление и реляционная алгебра были введены как инструмент над реляционной моделью. А вовсе не "сами по себе".
V>>И да, когда изучают реляционную алгебру, то непременно проходят операцию "проекция", сохранением результата которой и является индекс в классике. S>Простите, но это чушь. То, что получается в результате выполнения проекции, даже если его сохранить, никак не может быть индексом в классике. Если вам очень хочется поспорить про это — попробуйте применить такой "индекс" для оптимизации какого-нибудь запроса.
Таки настаиваю. Понимаешь, индекс можно построить даже по данным, которые не поддерживают операцию сравнения, хоть этого нельзя конкретно в MS SQL, но это лишь подробности MS SQL. Принципиально в таком индексе будет то, что объем данных проекции может быть гораздо меньше объема всех данных, поэтому операция выборки/ограничения по индексу может быть выполнена многократно эффективнее, чем по всем исходным данным. Вот так может приниматься решение — делать индекс кластерным или некластерным.
S>Скажем, вот у нас табличка
S>
S>create table person(id int identity primary key, name varchar(max) not null, gender char(1) not null, picture )
S>
S>Мы хотим оптимизировать запрос S>
S>select id from person where name = 'vdimas'
S>
S>Расскажите мне, результат какой операции "проекция" тут поможет так же, как S>
S>create index ByName on person(name, id)
S>
Еще раз большими буквами — любой некластерный индекс — это и есть проекция. В классике индексы некластерные изначально. Просто в MS SQL ввиду особенностей хранения блобов кластерные индексы оч популярны.
Я тебе скажу так, в достаточно большой системе, с многими миллионами записей движений и сотнеями справочников, одно лишь только изменение суррогатных ключей с типа int на shortint в справочниках и оформление индексов как некластерных у справочников, где записи достаточно большие (много полей) подняло производительность более чем в четверо. Вот зачем нужна проекция при построении индекса — это снижение объема перелопачиваемых данных при операциях над таблицами, проводимыми по этому индексу/ключу (фактически все операции из РА).
S>Бррр. Опять каша. Реляционная алгебра — это раздел математики, достаточно строго определённый. Она работает с реляциями.
Это прикланой раздел, который, каки любой прикадной раздел, что-то обслуживает. Конерктно реляционная алгебра была разработана для обслуживания реляционной модели. И она не может жить ВНЕ реляционной модели.
V>>Несвязный набор слов. Одно использует другое. SQL оперирует терминами реляционного исчисления, но стоимость операций реляционного исчисления недетерминирована. S>Это у вас несвязный набор слов. SQL отклоняется от реляционной алгебры, т.к. представляет компромисс между математической строгостью и вопросами реальной производительности. Терминами реляционного исчисления SQL никак не оперирует:
Наверно не понимаешь, что есть реляционное исчисление, а что есть реляционная алгебра, так? Это совсем не одно и то же.
S>Вопросы стоимости операций появляются только в тот момент, когда мы заменяем абстрактные операции расширенной РА в логическом плане запроса конкретными операциями физического плана запроса. Именно в этот момент появляется простор для оптимизаций, т.к. одному и тому же логическому плану запроса может соответствовать много различных физических планов запроса, отличающихся стоимостью.
Я не знаю, что есть логическое, а что есть физическое в твоем понимании? Использование разного порядка сканирования индексов — это физическое отличие или логическое? А ведь разные вещи, хотя с т.з. реляционного исчисления — это не имеет значения, но с т.з. реляционной алгебры — это разная последовательность императивных операций над разными таблицами-индексами. Я в свое время нарешался на практиках задач по составлению реляционных алгоритмов, заданных реляционным исчислением как условием (это почти SQL, только математический), что аж тошнило. И для случая отдельных индексов в т.ч. Индексы в этих задачах рассматриваются как отдельное отношение, где кортеж целиком совпадает со своим основным (и единственным) ключом.
DG>>>>> The object identity of two objects of the same type is the same, if every change to either object is also a change to the other object.
DG>>>после применения одного и того же изменения, идентичные объекты перестали быть идентичными. S>>Здесь ничто не изменилось
DG>как только в выделенном найдешь (или в другом месте текста про identity), что change объекта не имеет права создавать новые копии объекта, тогда продолжим разговор.
Операция конкатенации строк не вызывает изменение строк.
var y = "0";
var x = y;
Console.WriteLine(object.ReferenceEquals(x,y)); //Truevar z = y+"1";
Console.WriteLine(object.ReferenceEquals(x,y)); //все равно True
DG>>>как только в выделенном найдешь (или в другом месте текста про identity), что change объекта не имеет права создавать новые копии объекта, тогда продолжим разговор. S>>В выделенном не об этом. Где-нибудь в другом месте текста про identity по той ссылке тоже об этом нет. S>> Ну а кроме этого, в твоем примере нет и намека на попытку изменения объекта.
DG>это не формально. введи формальное определение в виде: изменение называется ..., а данная операция этому определению не удовлетворяет.
DG>зы DG>более сложный пример на тоже самое. есть два объекта y, z, потом они меняются на одно и тоже — и становятся не одинаковыми DG>
DG> string y = "2";
DG> string z = y;
DG> Console.WriteLine(Object.ReferenceEquals(z, y));
DG> y += "1";
DG> z += "1";
DG> Console.WriteLine(Object.ReferenceEquals(z, y));
DG>
DG>выдача DG>
DG>True
DG>False
DG>
string y = "2";
string z = y;
string y1 = y;string z1 = z;
Console.WriteLine(Object.ReferenceEquals(z, y));
y += "1";
z += "1";
Console.WriteLine(Object.ReferenceEquals(z, y));
Console.WriteLine(Object.ReferenceEquals(z1, y1));//Ну ты понял ;)
Здравствуйте, Sinclair, Вы писали:
V>>И ты пока тоже ничего не сформулировал. И под вопросом вообще разделение слоев абстракций, бо в классике абстракции — это градиент, коль не задано обратное, где на одном из полюсов используется минимум деталей, а на другом максимум. S>Ну откуда же может взяться градиент в заведомо дискретном множестве?
Кстати, вот типичная игра понятиями.
Цветовой градиент, он ведь в наших компьютерных реалиях тоже всегда по дискретному множеству. Не смущает?
S>После изменения значений переменных, ссылки, которые в них хранятся, больше не указывают на один и тот же объект.
как ты узнал, что они больше не ссылаются на один и тот же объект?
через ReferenceEquals? т.е. ты ReferenceEquals используешь и для проверки, что ссылки остались теми же, и для определения идентичности объектов?
но в определение явно указано, что это две разных функции: функция сравнения ссылок и функция проверки идентичности
S> Что RefEquals не может выступать в роли критерия идентичности?
конечно, потому что сравнение ссылок, а не сравнение объектов, что и следует из названия