использовать row_number()
select *, row_number() over(partition by InventoryId order by id) as newRevisionId
from tablename
ОБНОВЛЕНИЕ № 2
Это уменьшает потребность в обходе списка в связанном списке, Удаляют. Это представляет LruCacheNode, который имеет и ключ и значение. Ключ только используется при обрезке кэша. Вы могли получить лучшую производительность, если бы Вы записали свою собственную реализацию связанного списка, где каждым узлом по существу является LruCacheNode наряду со Следующей и Обратной ссылкой. Это - вид того, что делает LinkedHashMap (см. онидвавопросы о ).
public class LruCache<K, V>
{
private readonly int m_iMaxItems;
private readonly Dictionary<K, LinkedListNode<LruCacheNode<K, V>>> m_oMainDict;
private readonly LinkedList<LruCacheNode<K, V>> m_oMainList;
public LruCache(int iSize)
{
m_iMaxItems = iSize;
m_oMainDict = new Dictionary<K, LinkedListNode<LruCacheNode<K, V>>>();
m_oMainList = new LinkedList<LruCacheNode<K, V>>();
}
public V this[K key]
{
get
{
return BumpToFront(key).Value;
}
set
{
BumpToFront(key).Value = value;
}
}
public void Add(K key, V value)
{
LinkedListNode<LruCacheNode<K, V>> newNode = m_oMainList.AddFirst(new LruCacheNode<K, V>(key, value));
m_oMainDict.Add(key, newNode);
if (m_oMainList.Count > m_iMaxItems)
{
m_oMainDict.Remove(m_oMainList.Last.Value.Key);
m_oMainList.RemoveLast();
}
}
private LruCacheNode<K, V> BumpToFront(K key)
{
LinkedListNode<LruCacheNode<K, V>> node = m_oMainDict[key];
if (m_oMainList.First != node)
{
m_oMainList.Remove(node);
m_oMainList.AddFirst(node);
}
return node.Value;
}
public bool Contains(K key)
{
return m_oMainDict.ContainsKey(key);
}
}
internal sealed class LruCacheNode<K, V>
{
private readonly K m_Key;
private V m_Value;
public LruCacheNode(K key, V value)
{
m_Key = key;
m_Value = value;
}
public K Key
{
get { return m_Key; }
}
public V Value
{
get { return m_Value; }
set { m_Value = value; }
}
}
Необходимо будет представить вещи видеть, является ли это улучшением среды.
Незначительное обновление: Я обновил BumpToFront для проверки, чтобы видеть, ли узел уже в передней стороне на комментарий от Tim Stewart.
Разве точка кэша LRU не, чтобы позволить Вам обрезать кэш и выводить последний использованный материал?:-) Я не вижу кода для обрезки кэша. Так как Вы, скорее всего, хотите высокую производительность для получать примера использования, и пример использования для обрезки менее важен, почему бы не разгрузить обслуживание списка к процессу для обрезки?
IOW, просто бросьте записи в кэш, но добавьте метку времени к ним на извлечении. Не переупорядочивайте записи, просто отмечайте их каждый раз, когда они используются. Мог быть истинная метка времени DateTime или мог быть простой счетчик в классе, самое большое количество последний раз использовалось. Затем в процессе для обрезки просто обходят целое дерево и удаляют записи с самыми старыми штампами.
С аппаратными кэшами, вместо наличия говорят, что 128 элементов и поддержание порядка пунктов 1-128, у Вас могло бы быть оно как 32 x 4, таким образом, 32 строки 4 элементов каждый. Первые 5 битов адреса определили бы, какая из 32 строк, которые адрес отобразит на, затем Вы искали бы только эти 4 объекта, и если не найденный заменой самый старый из 4.
Это намного быстрее, и является IIRC в 10% частоты успешных обращений кэша 1 x 128.
Для перевода Вы были бы вместо одного связанного списка, иметь несколько, так пересечение их было намного быстрее. У Вас должен был бы быть способ определить который список конкретный объект, отображенный на.
Точка быть, поскольку Ваш список увеличивается в размере, Вы получаете убывающую доходность от попытки поддержать с идеальной точностью точный порядок каждого элемента в списке. Вы могли бы даже быть более обеспечены с незаказанным списком, и случайным образом заменяющий любой элемент, когда у Вас есть неудачное обращение в кэш. Зависит от размера Вашего списка и штрафа за мисс по сравнению со стоимостью ведения списка.