Russian Qt Forum

Qt => Model-View (MV) => Тема начата: titan83 от Октябрь 02, 2016, 10:35



Название: [РЕШЕНО] Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 10:35
Уважаемые коллеги, здравствуйте.
Работа с Qt MVC получается неплохо, но возник вопрос: на небольших моделях (пара тысяч ячеек) все работает неплохо, но если набор данных достаточно большой (сейчас есть 10000 ячеек), то загрузка (с сервера sql) получается долгой (15-20 секунд), это, в принципе, еще терпимо, но будут таблицы под 100000 ячеек, и это будет шляпа.
Вполне логично возникает идея не загружать весь набор данных я только небольшую часть, видимую пользователю. И вот тут есть непонимание: допустим, я получаю часть набора (например, 100-200 записей) из базы, но если я буду говорить в модели, что у меня rowCount() == 200, то я получу неправильный скроллбар (не такой, как для итоговых 50000 записей).
Собственно вопрос: как правильно работать с большими массивами данных в моделях?
Думаю, что есть готовые алгоритмы, но пока не нашел.
Спасибо.


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 12:12
ИМХО - модели в Qt неприспособлены для больших объемов данных.

Как вариант - перейти к постраничной обработке. Т.е. получаем кол-во записей, делим на помещающиеся на экране/таблице/магическое число, получаем количество страниц :)


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 13:14
ИМХО - модели в Qt неприспособлены для больших объемов данных.
Традиционный бред. :)

если набор данных достаточно большой (сейчас есть 10000 ячеек), то загрузка (с сервера sql) получается долгой (15-20 секунд)
Какое-то огромное время для такого небольшого объема записей.
Как у вас получается так долго получать данные? Что это за сервер БД?


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 14:07
Цитировать
Какое-то огромное время для такого небольшого объема записей.
Как у вас получается так долго получать данные? Что это за сервер БД?
Здравствуйте, база MSSQL, программа работает под линуксом.
В принципе, время доступа сопоставимо с нативной программой под виндовсом (может на пару секунд больше, но моя прога запускается на ARM 1Ghz, а не на Core i7), думаю, это из-за того, что запрос довольно сложный - несколько inner join, десяток полей.
После загрузки работает нормально, но вот время этой самой загрузки слегка напрягает.


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 14:17
Здравствуйте, база MSSQL, программа работает под линуксом.
В принципе, время доступа сопоставимо с нативной программой под виндовсом (может на пару секунд больше, но моя прога запускается на ARM 1Ghz, а не на Core i7), думаю, это из-за того, что запрос довольно сложный - несколько inner join, десяток полей.
После загрузки работает нормально, но вот время этой самой загрузки слегка напрягает.
Я правильно понял, что у вас на арме под linux запускается сервер MSSQL?


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 15:22
[offtop] загрузите ка в стандартную sql модель пару тройку десятков миллионов записей... Посмотрите на получившееся тормозное страшное чудо и поймете, что большие объемы данных и модели Qt, это несовместимо.


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 15:42
[offtop] загрузите ка в стандартную sql модель пару тройку десятков миллионов записей... Посмотрите на получившееся тормозное страшное чудо и поймете, что большие объемы данных и модели Qt, это несовместимо.
Ооо. Уже пару тройку десятков миллионов... Вроде у ТС были жалкие 10 тысяч. :)
Модели в Qt тормозят не более самой базы данных. Главное не пользоваться стандартными прокси-моделями для сортировки таких выборок.

Ну и не устану повторять: такие выборки по 100 тысяч строк (не говоря уже о смехотворных десятках миллионов) совершенно бесполезны. Ни один человек с ними ничего сделать не сможет. Нужны нормальные системы фильтрации.


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 16:12
Так вы определитесь.
Или же я прав - модели Qt не годятся при работе с большими объемами данных.
Или же модели Qt способны переварить миллионы - и тогда я неправ :D


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 16:20
Или же модели Qt способны переварить миллионы - и тогда я неправ :D
Конечно способны. Модель в Qt это универсальный интерфейс для отображения любых данных. А вот реализации этих интерфейсов могут быть разные.
Модель Qt может легко использоваться для отображать таблиц с сотнями миллионов записей, и это будет вообще без загрузки процессора.


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 16:40
Цитировать
Я правильно понял, что у вас на арме под linux запускается сервер MSSQL?
Нет.
Сервер MSSQL - отдельный, под виндовз, обычно в одной локалке, но может быть и в облаке.
мой ARM - один из возможных клиентов, на нем работает только моя qt-программа.


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 16:44
Нет.
Сервер MSSQL - отдельный, под виндовз, обычно в одной локалке, но может быть и в облаке.
мой ARM - один из возможных клиентов, на нем работает только моя qt-программа.
Ну тогда выборку делает сервер MSSQL на нормальной машине. Неужели эта выборка готовиться десятки секунд?
Вы можете сделать руками эту выборку из какого-то клиента БД и посмотреть за сколько она будет формироваться.


Название: Re: Большие модели
Отправлено: Racheengel от Октябрь 02, 2016, 16:47
Или же модели Qt способны переварить миллионы - и тогда я неправ :D

Стандартные имплементации этих моделей не способны.
Оверхэд слишком большой.
Всегда приходится свою логику городить.



Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 17:23
Нет.
Сервер MSSQL - отдельный, под виндовз, обычно в одной локалке, но может быть и в облаке.
мой ARM - один из возможных клиентов, на нем работает только моя qt-программа.
Ну тогда выборку делает сервер MSSQL на нормальной машине. Неужели эта выборка готовиться десятки секунд?
Вы можете сделать руками эту выборку из какого-то клиента БД и посмотреть за сколько она будет формироваться.
Так и сделал - запустил нативный клиент на своем ноуте - он открывает ту же таблицу за 4-5 секунд, моя программа за 15-17 секунд. Но при этом непосредственно выборка занимает 6,5 секунд, что, на мой взгляд, нормально (учитывая драйвера freetds для mssql). Остальное время (7-7,5 секунд) уходит на заполнение модели.
Так что, видимо, надо смотреть в сторону оптимизации заполнения внутренних данных.
Код:
    qDebug() << "before sql" << QTime::currentTime().toString("mm:ss.zzz");
    QWshDatabase::SqlRecordsList data = DB->wshData(_vars["WshCode"], _vars["Filter"]);
    qDebug() << "after sql" << QTime::currentTime().toString("mm:ss.zzz");
    qDebug() << "before model" << QTime::currentTime().toString("mm:ss.zzz");
    resetModel();
    _data.resize(_hHeaders.size());

    if (_data.size() > 0)
        for (int i = 0; i < data.size(); i++) {
            QWshCell* newCell = new QWshCell();
            int currentRow = data.at(i).value("sTag").toString().toInt() - 1;
            _data[currentRow].resize(_vHeaders.size());
            for (int j = 0; j < data.at(i).count(); j++)
                newCell->setValue(data.at(i).field(j).name(), data.at(i).field(j).value().toString());
            newCell->cellStyle().parseInputString();
            _data[currentRow][testTagPos(data.at(i).value("tTag").toString())] = newCell;
        }
    qDebug() << "after model" << QTime::currentTime().toString("mm:ss.zzz");
Код:
before sql "16:57.813"
after sql "17:04.676"
before model "17:04.677"
after model "17:11.416"
Код:
QVector<QVector< QPointer<QWshCell>>> _data
В крайнем случае буду думать, что ARM 1GHz не вывозит быстрее))


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 17:28
Отключите обновление таблицы на момент заполнения данными, время должно сократиться.


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 17:31
А для чего это перекладывание?
Вы получаете QWshDatabase::SqlRecordsList data, вот и храните этот список, и данные берите от туда, когда вьюшка их будет спрашивать через data().
Что достигается этим копированием из data в _data?


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 17:35
Отключите обновление таблицы на момент заполнения данными, время должно сократиться.
спасибо.
функция resetModel() в начале листинга содержит две строки:
beginResetModel();
endResetModel();
модель не обновляется.
пробовал ставить beginResetModel() в начале, а endResetModel() - в конце. Нет эффекта.


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 17:38
Не модели, а таблицы :D Хотя мб и не поможет, я пока не видел какой тип View вы используете ;D


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 17:43
Не модели, а таблицы :D Хотя мб и не поможет, я пока не видел какой тип View вы используете ;D
Я использую QTableView со своим делегатом, будьте добры, подскажите как можно "отключить обновление" именно в представлении? Я думал, что beginResetModel() и иже с ним, как раз и сообщают представлению, что с графическим обновление надо подождать.


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 17:47
А для чего это перекладывание?
Вы получаете QWshDatabase::SqlRecordsList data, вот и храните этот список, и данные берите от туда, когда вьюшка их будет спрашивать через data().
Что достигается этим копированием из data в _data?
В принципе, это разумно, но перед релизом я такой рефакторинг делать точно не буду))
К тому же данных должны быть немного распарсены перед использованием, ваш подход тоже разумен - парсить прямо перед отправкой во вью.
Я сейчас осмысливаю опыт с этого проекта, чтобы в следующем уже сделать все разумнее и проще.


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 18:17
В принципе, это разумно, но перед релизом я такой рефакторинг делать точно не буду))
Вы серьезно?
Да что там рефакторить? Метод data модели? :)


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 18:19
ui.tableView->setUpdatesEnabled(bool )


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 18:21
ui.tableView->setUpdatesEnabled(bool )
Это ничего не даст.


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 18:23
ui.tableView->setUpdatesEnabled(bool )
Спасибо, посмотрел - это метод QWidget, не думаю, что это как-то поможет - основная работа идет с массивами данных, а не с виджетом.


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 18:30
В принципе, это разумно, но перед релизом я такой рефакторинг делать точно не буду))
Вы серьезно?
Да что там рефакторить? Метод data модели? :)
Если я просто выводил один-в-один то, что пришло из БД во вью, то, конечно, я бы и не делал лишнюю прокладку. Но, к сожалению, я получаю описание ячейки (цвета фона-шрифта, состояние ячейки, поведение), мне надо его перевести в вид, удобный для как раз таки метода data() модели. Там около 350 строк кода в паре классов, и я не хотел бы переносить их в модель, т.к. не люблю классы-гиганты (>300-350 строк).
В любом случае - спасибо за участие.


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 18:32
Коллеги, мы все же немного отвлеклись. Главный вопрос для меня - возможно ли ЧАСТИЧНО загружать данные в модель, именно те, которые требуются предсталению в данный момент?


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 18:50
Можно, если давать частичный запрос. По сути вы запрашиваете слишком много информации. Вам нужно запрашивать меньше.

PS вы немного не понимаете про виджет. При обновлении данных в View происходит следующее - каждая новая запись создаётся, отображается и только потом создаётся следующая. Убрав update виджета, мы убираем отображение из этой цепочки, что может сэкономить пусть и малую, но существенную часть.

PPS для Old и иных одаренных - да, при правильном создании модели данной ситуации не будет. Однако хз что там за модель и зачастую это может помочь :D


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 19:05
PS вы немного не понимаете про виджет. При обновлении данных в View происходит следующее - каждая новая запись создаётся, отображается и только потом создаётся следующая. Убрав update виджета, мы убираем отображение из этой цепочки, что может сэкономить пусть и малую, но существенную часть.
Это вы не понимаете. Все совсем не так. Если модель не уведомляет view о вставке/удалении строки, то ничего построчно не обновляется.
В данном случает, view обновится после отработки вышеприведенного кода - один раз. Правда не понятно, для чего вызывается resetModel до обвновления _data, а не после... но это частности. :)


Название: Re: Большие модели
Отправлено: Bepec от Октябрь 02, 2016, 19:09
Вы, как и я, в душе не чаете что там в модели. Так же как и нет уверенности в том, что приведенный код выдернут из проекта :D


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 19:39
Вы, как и я, в душе не чаете что там в модели.
Там "чаять" нечего.


Название: Re: Большие модели
Отправлено: Old от Октябрь 02, 2016, 19:42
Коллеги, мы все же немного отвлеклись. Главный вопрос для меня - возможно ли ЧАСТИЧНО загружать данные в модель, именно те, которые требуются предсталению в данный момент?
Посмотрите, поддерживает ли MSSQL ключевые слова LIMIT и OFFSET, но лучше продумайте мощную систему фильтров, что-бы пользователю не приходилось ковыряться в 100500 строках не нужных ему данных.


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 20:39
Коллеги, мы все же немного отвлеклись. Главный вопрос для меня - возможно ли ЧАСТИЧНО загружать данные в модель, именно те, которые требуются предсталению в данный момент?
Посмотрите, поддерживает ли MSSQL ключевые слова LIMIT и OFFSET, но лучше продумайте мощную систему фильтров, что-бы пользователю не приходилось ковыряться в 100500 строках не нужных ему данных.
MSSQL не поддерживает LIMIT (только TOP), но тут коллеги по проекту помогут.
Фильтры будут однозначно.
ЗЫ по resetModel() вы правы, надо бы сначала beginResetModel(), а потом endResetModel(), но это, действительно не влияет, пока. Но переделаю правильно, точно)) Уже ставлю задачу в гитлаб.


Название: Re: Большие модели
Отправлено: titan83 от Октябрь 02, 2016, 20:39
Думаю, тему пора закрывать.
Всем спасибо за интересную дискуссию.