Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Что поменять в работе с БД для изменения логики отборов?  [new]
andreys3
Member

Откуда:
Сообщений: 3
Приветствую!
В БД имеется таблица с количеством записей 29 000 000.
Есть индексированное поле Company, которое дает информацию о принадлежности записи конкретной компании. Есть поле hash. Из нескольких записей с одинаковым hash актуальной является последняя запись.
На одну компанию приходится от нескольких тысяч до нескольких сот тысяч записей в этой таблице.
Сейчас выбирается по 10 000 записей для каждой компании - сначала с первой (с самым малым id), затем - после последней полученной в предыдущем запросе. Запрос 10 000 отрабатывает за 5-10 секунд, на сервере все ок.
Актуальные записи отбираются на клиенте.
Так как актуальных записей меньше половины - есть задача на сервере отбирать актуальные данные. Однако, записи с одинаковыми hash могут быть по всей таблице, как в конце, так и в начале.
Соответственно, собираем все записи, отбираем актуальные, затем отдаем 10 000, и так каждый раз.
Но в этом случае сильно возрастает нагрузка на сервер, что объяснимо.
Подскажите, что можно предпринять в такой ситуации.
Спасибо!
10 ноя 15, 17:20    [18396124]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7868
andreys3,

ничего не понятно, продемонстрируйте примером.
10 ноя 15, 18:30    [18396514]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Serg_77m
Member

Откуда: Донецк
Сообщений: 237
andreys3
Приветствую!
В БД имеется таблица с количеством записей 29 000 000.
Есть индексированное поле Company, которое дает информацию о принадлежности записи конкретной компании. Есть поле hash. Из нескольких записей с одинаковым hash актуальной является последняя запись.
На одну компанию приходится от нескольких тысяч до нескольких сот тысяч записей в этой таблице.
Сейчас выбирается по 10 000 записей для каждой компании - сначала с первой (с самым малым id), затем - после последней полученной в предыдущем запросе. Запрос 10 000 отрабатывает за 5-10 секунд, на сервере все ок.
Они что, порциями выбираются? Не все сразу для одной компании, а по 10000 штук? А выбрать все сразу не быстрее будет?

Я правильно понимаю задачу? В таблице есть индекс по паре полей Company+id, выборка порций делается чем-то вроде:
select top 10000 ... from ... where Company=@Company and id>@prev_id order by id
где параметр @prev_id подставляет клиент после получения предыдущей порции.

andreys3
Актуальные записи отбираются на клиенте.
Так как актуальных записей меньше половины - есть задача на сервере отбирать актуальные данные. Однако, записи с одинаковыми hash могут быть по всей таблице, как в конце, так и в начале.
Соответственно, собираем все записи, отбираем актуальные, затем отдаем 10 000, и так каждый раз.
Но в этом случае сильно возрастает нагрузка на сервер, что объяснимо.
Подскажите, что можно предпринять в такой ситуации.
Спасибо!
Радикальное решение: добавить в таблицу битовое поле - признак актуальности записи, и написать триггер, который будет его поддерживать. Так чтобы оно было 1 на актуальных записях, и 0 на неактуальных. Включить это поле в индекс. Или лучше в условие фильтра индекса, если версия сервера позволяет.

А обязательно записи выбирать в порядке возрастания id? По hash сортировать нельзя?
10 ноя 15, 18:46    [18396638]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Mike_za
Member

Откуда: Москва
Сообщений: 1176
andreys3,

Хеш чего? Зачем он? Схему таблицы привидите
10 ноя 15, 20:57    [18397165]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Что поменять
Guest
andreys3,

до слова "соответственно" более-менее понятно о чем речь, но дальше какая-то немножко бессмыслица
10 ноя 15, 22:16    [18397433]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
andreys3,

Храните или флаг актуальности, как уже предложили, или вообще в отдельной таблице/секции. Нафига вам неактульные данные каждый раз перелопачивать?
11 ноя 15, 01:18    [18397799]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
andreys3
Member

Откуда:
Сообщений: 3
Уточняю.
Имеется в том числе 2 таблицы:
[IMG]http://s017.radikal.ru/i421/1511/ce/2e4f04a65749.png[/IMG]
1. Из таблицы Transaction отбираются записи, соответствующие определенному CompanyID.
2. Затем из таблицы Metric выбираются метрики, соответствующие списку TransactionID из результата, полученного в результате (1). - по 10000 за 1 обращение.
Из записей с одинаковым MetricHashWDate (хэш Name, DateTime, Resource и еще кое-чего из другой таблицы) только одна является актуальной - с максимальным metricID.
Индексы есть по metricID (PK), DateTime, TransactionID (отдельные) в таблице Metric, по CompanyID - в таблице Transaction.
Чтобы не хранить неактуальные записи - удалять либо помечать, надо будет при добавлении данных в БД каждый раз проходить базу на предмет поиска идентичных MetricHashWDate, что, насколько я понимаю, тоже не очень хорошо. В одной транзакции, как правило, приходит от 1 до 100 метрик.
11 ноя 15, 16:20    [18401118]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Добрый Э - Эх
Guest
andreys3,

непонятно, помощь тут кому нужна - тебе или нам?
где структуры таблиц? где запрос/программа/скрипт или что там у тебя выполняется, реализующее описанную тобой логику?
где тестовый набор данных и желаемый вид результата на них?

мы всё должны придумать сами???
11 ноя 15, 16:42    [18401316]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Serg_77m
Member

Откуда: Донецк
Сообщений: 237
andreys3
Из записей с одинаковым MetricHashWDate (хэш Name, DateTime, Resource и еще кое-чего из другой таблицы) только одна является актуальной - с максимальным metricID.
Индексы есть по metricID (PK), DateTime, TransactionID (отдельные) в таблице Metric, по CompanyID - в таблице Transaction.
Чтобы не хранить неактуальные записи - удалять либо помечать, надо будет при добавлении данных в БД каждый раз проходить базу на предмет поиска идентичных MetricHashWDate, что, насколько я понимаю, тоже не очень хорошо.
Но если не помечать записи при добавлении, придётся ловить дубли при выборке. Что бывает чаще?

А всю базу проходить не надо: есть индекс по DateTime, а идентичные MetricHashWDate могут быть только при равных Datetime. Или нет? На крайний случай можно и индекс по MetricHashWDate добавить, или индекс по Datetime сделать составным по Datetime+MetricHashWDate.
11 ноя 15, 17:27    [18401698]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
aleks2
Guest
andreys3
Чтобы не хранить неактуальные записи - удалять либо помечать, надо будет при добавлении данных в БД каждый раз проходить базу на предмет поиска идентичных MetricHashWDate, что, насколько я понимаю, тоже не очень хорошо.

Не фсех "идентичных MetricHashWDate", а токмо актуальных. Туго у тя с воображением.

А ваще, с индексами у тя бардак.
Нужен (TransactionID, MetricHashWDate, DateTime) в таблице Metric.
12 ноя 15, 06:28    [18403834]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
andreys3
Member

Откуда:
Сообщений: 3
Сейчас работает так - Entity Framework 5 (без отбора неактуальных метрик):
Expression<Func<Metric, bool>> expression;
                IEnumerable<Metric> result;
                expression = x => (x.Transaction.CompanyID == companyId) && (x.MetricId > metricIdLastOnDevice);
                result = Context
                    .Metrics
                    .Include("Analytics")
                    .Include("ApplicationVersion")
                    .Include("Transaction")
                    .Where(expression)
                    .OrderBy(x => x.MetricId)
                    .Take(numberOfMetrics);
                return result;

Пробовал вариант ADO.NET (отбор всех данных, затем отбираем актуальные):
List<Metric> result = new List<Metric>();
             string queryString =
                " select * from( "
                + " select max(MetricId)as metricId from( "


                + " SELECT top " + numberOfMetrics + " * "
                + " FROM ( "
                + " SELECT transactionid "

                + " FROM DataBase.dbo.[Transaction] "
                + " WHERE CompanyID = '"
                + companyId
                + "'"
                + " ) AS #transaction "
                + " inner join DataBase.dbo.metric on transaction_transactionid = #transaction.transactionid where DataBase.dbo.metric.metricid > " + metricIdLastOnDevice
                + " ) as #maxMetrics "
                + " group by #maxMetrics.MetricHashWDate "
                + " ) as #Metrics "
                + " inner join DataBase.dbo.metric on #Metrics.metricId = DataBase.dbo.Metric.MetricId "
                + " order by #Metrics.MetricId";

Почитав ваши комментарии, решил, что надо попробовать потестить вариант, когда при укладке данных в базу проверяется наличие идентичных по MetricHashWDate записей и их удаление. Возможно, это не будет занимать слишком много времени.
23 ноя 15, 12:03    [18458651]     Ответить | Цитировать Сообщить модератору
 Re: Что поменять в работе с БД для изменения логики отборов?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
вы бы для начала запросы в SSMS отработали, а потом засовывали их в (извините) Entity Framework
23 ноя 15, 12:17    [18458775]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить