In-Memory SQL/NoSQL - сохраняйте возможность запроса - возможно, используйте MySQL или SQL Server

Я хотел бы иметь возможность запускать набор записей / документов в хранилище данных, но всегда сохранять эти записи в оперативной памяти. Мне нужно всего лишь около 1,5 ГБ до 2 ГБ оперативной памяти (потенциально меньше). Это будет основано на сервере, а не встроено.

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

Я знаю, что MySQL может создавать таблицы на основе памяти, но не уверен, что люди используют эту функцию для того, о чем я думаю. Может ли SQL Server закреплять таблицы в памяти? Весь стол?

Какие еще хранилища данных мне следует посмотреть? Запросы Map/Reduce style также подойдут, если быстро.

4 ответа

SQLLite может работать в памяти для решения реляционной базы данных. Для нереляционной базы данных RavenDB может работать в памяти.

VoltDB - это совместимая с ACID база данных SQL в памяти, оптимизированная для высокоскоростной OLTP. Он работает на 64-битной Linux или Mac OS X, имеет версию сообщества с открытым исходным кодом и клиентские библиотеки на нескольких языках.

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

Если вы можете представить свои данные в виде коллекции объектов, то вы можете просто использовать Linq в качестве функции "расширенного запроса" и делать все это в памяти: это будет НАМНОГО быстрее, чем практически все решения для баз данных. Если вы можете хранить все свои данные в памяти, то даже не беспокойтесь о базе данных.

Примечание: если вы делаете это в.NET, то вам придется строить свой проект в 64-битном режиме, потому что вы не можете иметь коллекцию, которая имеет более ~1,5 ГБ данных в оперативной памяти в 32-битном приложении. Если вы не можете собрать / запустить в 64-битном режиме, то вам может потребоваться база данных.

Обновить

Я не уверен, что следую тому, что вы говорите: я не совсем уверен, что такое распространенная система, и это заставило бы меня поверить, что я не использую распространенную систему. Я также не знаю, что такое "доморощенный" объект или что такое "доморощенная" система.NET. Я использую только стандарт.NET 4.0, и когда я говорю объекты, я специально имел в виду, что вы пишете классы, которые могут хранить ваши данные. После этого вы загружаете свои данные в память (я не знаю, как вы получаете эти данные: файл, базу данных, сеть и т. Д.), А затем Linq выполняет ORM для вас. Безопасность потоков имеет значение только тогда, когда вы обращаетесь к своей внутренней коллекции объектов, и вы можете сделать это с помощью простой блокировки.

О, и если это доморощенная система.NET - размещаются ли эти объекты на сервере и получают ли они поражение от нескольких клиентов?

Для данных, с которыми я имею дело, мне не нужны никакие расширенные возможности запросов (ни в памяти, ни для получения их из базы данных), поэтому мы храним все, что не вписывается в память, во встроенную базу данных. ( LevelDB). Таким образом, все наши данные хранятся на диске, и, когда нам это нужно, мы выбираем кратчайший / быстрый маршрут, чтобы поместить их в память. Переход по сети только замедлит вас, так что вы можете сделать это, но делать это только тогда, когда это абсолютно необходимо (т. Е. У вас есть жесткое ограничение на то, что ваши данные объемом 2 ГБ находятся в базе данных где-то, кроме вашей локальной машины).

Я должен согласиться с Лириком здесь. В терминах.Net использование объектов для ваших данных и LINQ для запроса их коллекции должно быть одним из самых быстрых способов сделать то, о чем вы просите, но при этом иметь в своем распоряжении богатый язык запросов.

Если вас беспокоит размер коллекции, и если вы сможете хранить всю информацию в памяти, вы могли бы взглянуть на такие проекты, как Memcached, чтобы помочь вам.

ОБНОВИТЬ

Я построил пример использования Linq с объектом критерия для запроса списка продуктов (хотя он может легко быть датированным с помощью Linq to Sql)

Сначала пример класса продукта:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Linq_Question
{
    public class Product
    {
        public enum Categories
        {
            CatOne,
            CatTwo,
            CatThree
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public Categories Category { get; set; }
        public decimal Price { get; set; }

    }
}

Теперь пример класса Критерии продукта

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Linq_Question
{
    public class ProductCriteria
    {
        public Product.Categories? WhereCategoryIs { get; set; }
        public decimal? WherePriceIsGreaterThan { get; set; }
        public decimal? WherePriceIsLessThan { get; set; }
        public string WhereNameContains { get; set; }

        public ProductCriteria()
        {

        }
    }
}

Пример репозитория - использование списков

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace Linq_Question
{
    public class ProductRepository
    {
        private List<Product> products;

        public ProductRepository()
        {
            products = new List<Product>();
            products.Add(new Product() { Category = Product.Categories.CatOne, Id = 1, Name = "Product 1", Price = 100 });
            products.Add(new Product() { Category = Product.Categories.CatTwo, Id = 2, Name = "Product 2", Price = 120 });
            products.Add(new Product() { Category = Product.Categories.CatThree, Id = 3, Name = "Product 3", Price = 300 });
            products.Add(new Product() { Category = Product.Categories.CatOne, Id = 4, Name = "Product 4", Price = 400 });
            products.Add(new Product() { Category = Product.Categories.CatTwo, Id = 5, Name = "Product 5", Price = 500 });
            products.Add(new Product() { Category = Product.Categories.CatThree, Id = 6, Name = "Product 6", Price = 600 });
        }

        public IEnumerable<Product> Retrieve(ProductCriteria criteria)
        {
            return this.products.Where(FilterProducts(criteria));
        }

        private Func<Product, bool> FilterProducts(ProductCriteria criteria)
        {
            Expression<Func<Product, bool>> predicate = PredicateBuilder.True<Product>();
            List<IProductFilter> filters = new List<IProductFilter>();
            filters.Add(new PriceIsGreaterThanFilter());
            filters.Add(new CategoryFilter());

            foreach (var item in filters)
            {
                if (item.IsValidFilter(criteria))
                {
                    predicate = predicate.And(item.ApplyFilter(criteria));
                }
            }
            return predicate.Compile();
        }
    }
}

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

Вот интерфейс IProductFilter и несколько примеров фильтров

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace Linq_Question
{
    public interface IProductFilter
    {
        bool IsValidFilter(ProductCriteria criteria);
        Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria);
    }

    public class CategoryFilter : IProductFilter
    {
        public bool IsValidFilter(ProductCriteria criteria)
        {
            return (criteria.WhereCategoryIs.HasValue);
        }

        public Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria)
        {
            return (p => p.Category == criteria.WhereCategoryIs.GetValueOrDefault());
        }
    }

    public class PriceIsGreaterThanFilter : IProductFilter
    {
        public bool IsValidFilter(ProductCriteria criteria)
        {
            return (criteria.WherePriceIsGreaterThan.HasValue);
        }

        public Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria)
        {
            return (p => p.Price > criteria.WherePriceIsGreaterThan.GetValueOrDefault());
        }
    }
}

Обратите внимание, что вам понадобится класс PredicateBuilder - найден http://www.albahari.com/nutshell/predicatebuilder.aspx

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

namespace Linq_Question
{
    public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }
        public static Expression<Func<T, bool>> False<T>() { return f => false; }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                            Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                             Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }
    }
}

Наконец, вот небольшое консольное приложение, демонстрирующее идею в действии:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Linq_Question
{
    class Program
    {
        static void Main(string[] args)
        {
            ProductRepository repo = new ProductRepository();
            Console.WriteLine("Items over 100");
            foreach (var item in repo.Retrieve(new ProductCriteria() { WherePriceIsGreaterThan = 100 }))
            {
                Console.WriteLine(string.Format("Name {0}, Category {1}, Price {2}", item.Name, item.Category, item.Price));
            }
            Console.WriteLine("Items with a Category of Two");
            foreach (var item in repo.Retrieve(new ProductCriteria() { WhereCategoryIs = Product.Categories.CatTwo }))
            {
                Console.WriteLine(string.Format("Name {0}, Category {1}, Price {2}", item.Name, item.Category, item.Price));
            }

            Console.Read();

        }
    }
}

Вы можете расширить эту идею, чтобы добавить несколько фильтров и даже решить, должна ли функция, возвращаемая из IProductFilter, иметь выражение И или ИЛИ для выражения.

Фильтры могут быть введены в хранилище, что позволяет легко их менять во время выполнения.

Я надеюсь, что это дает вам некоторые идеи.

Другие вопросы по тегам