:: Visual Foxpro, Foxpro for DOS
Кол-во записей в группе (оптимизация)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Приветствую.
Есть курсор номеров, которые разбиты по группам.
Задача получить кол-во номеров в каждой группе.
В таблице десятки МЛН записей. Возможно ли и как оптимизировать подобный запрос?
VFP 9 SP2

CLEAR
SYS(3054,12)
SET ENGINEBEHAVIOR 80
CREATE CURSOR Spisok (Nomer C(9), NG C(7))
INSERT INTO Spisok VALUES ('AA1111111', '1111111')
INSERT INTO Spisok VALUES ('AA1111112', '1111111')
INSERT INTO Spisok VALUES ('AA1111113', '1111111')
INSERT INTO Spisok VALUES ('AA1111114', '1111111')
INSERT INTO Spisok VALUES ('AA1111115', '2222222')
INSERT INTO Spisok VALUES ('BB1111111', '2222222')
INSERT INTO Spisok VALUES ('CC1111111', '2222222')
INSERT INTO Spisok VALUES ('AA1111116', '2222222')
INSERT INTO Spisok VALUES ('EE1111112', '2222222')
INSERT INTO Spisok VALUES ('AA1111117', '3333333')
INSERT INTO Spisok VALUES ('DD1111111', '3333333')
INSERT INTO Spisok VALUES ('EE1111111', '4444444')
INSERT INTO Spisok VALUES ('CC1111112', '5555555')
INDEX ON NG TAG NG
BROWSE LAST NOWAIT
*курсор по группам
nQntInGr= 5
SELECT NG, Qnt;
FROM (SELECT NG, COUNT(NG) Qnt FROM Spisok GROUP BY NG HAVING Qnt<=nQntInGr) Tmp;
ORDER BY Qnt;
INTO CURSOR GrCurs
BROWSE LAST NOWAIT
*курсор номеров
SELECT Sp.*,Gr.Qnt FROM Spisok Sp;
INNER JOIN GrCurs Gr ON Sp.NG=Gr.NG;
ORDER BY Gr.Qnt;
INTO CURSOR ResCurs
BROWSE LAST NOWAIT
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Sawradym

Сообщений: 2244
Откуда: Винница
Дата регистрации: 15.05.2007
VeterVFP
Приветствую.
Есть курсор номеров, которые разбиты по группам.
Задача получить кол-во номеров в каждой группе.
В таблице десятки МЛН записей. Возможно ли и как оптимизировать подобный запрос?
VFP 9 SP2

CLEAR
SYS(3054,12)
SET ENGINEBEHAVIOR 80
CREATE CURSOR Spisok (Nomer C(9), NG C(7))
INSERT INTO Spisok VALUES ('AA1111111', '1111111')
INSERT INTO Spisok VALUES ('AA1111112', '1111111')
INSERT INTO Spisok VALUES ('AA1111113', '1111111')
INSERT INTO Spisok VALUES ('AA1111114', '1111111')
INSERT INTO Spisok VALUES ('AA1111115', '2222222')
INSERT INTO Spisok VALUES ('BB1111111', '2222222')
INSERT INTO Spisok VALUES ('CC1111111', '2222222')
INSERT INTO Spisok VALUES ('AA1111116', '2222222')
INSERT INTO Spisok VALUES ('EE1111112', '2222222')
INSERT INTO Spisok VALUES ('AA1111117', '3333333')
INSERT INTO Spisok VALUES ('DD1111111', '3333333')
INSERT INTO Spisok VALUES ('EE1111111', '4444444')
INSERT INTO Spisok VALUES ('CC1111112', '5555555')
INDEX ON NG TAG NG
BROWSE LAST NOWAIT
*курсор по группам
nQntInGr= 5
SELECT NG, Qnt;
FROM (SELECT NG, COUNT(NG) Qnt FROM Spisok GROUP BY NG HAVING Qnt<=nQntInGr) Tmp;
ORDER BY Qnt;
INTO CURSOR GrCurs
BROWSE LAST NOWAIT
*курсор номеров
SELECT Sp.*,Gr.Qnt FROM Spisok Sp;
INNER JOIN GrCurs Gr ON Sp.NG=Gr.NG;
ORDER BY Gr.Qnt;
INTO CURSOR ResCurs
BROWSE LAST NOWAIT

Rол-во номеров в каждой группе.
nQntInGr= 5
SELECT NG, Count(*) As Qnt;
FROM Spisok;
GROUP BY NG;
HAVING Qnt<=nQntInGr;
ORDER BY Qnt;
INTO CURSOR GrCurs


------------------
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Sawradym, да, это я просто из своего контекста вырвал (зачем то подзапрос нужен был более сложный там).
Но задачу оптимизации то это не решает
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Оптимизации чего?
VeterVFP
получить кол-во номеров в каждой группе.
Это единственный запрос который показал Владимир, и он вполне себе оптимален.
Если же нужно получать именно "СПИСОК номеров в каждой группе состоящей менее чем из N (5 в примере) номеров" - ну это совершенно другое дело. И в общем случае сверх-оптимально на SQL не решается. Даже просто получить "кол-во номеров по группам состоящим менее чем из N (5 в примере) записей" оптимально на SQL (по крайней мере фоксовом) не сделать... Тут больше подойдёт процедурный подход, с "ранними" выходами из циклов по элементам группы.

P.S. Запрос оптимален, поскольку для решения такой задачи в любом случае требуется доступ к КАЖДОЙ записи исходной таблицы - иначе их не "пересчитать".


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 26.01.18 14:20
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
Igor Korolyov
оптимально на SQL (по крайней мере фоксовом) не сделать
Если не фокс, то оконными функциями.


------------------
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Они не сильно помогут в плане "получения количеств". Вот в задаче "получения списка" - да, там при правильном применении можно будет "за 1 проход" всё организовать. В фоксе - действительно на SQL только подзапросом с группировкой, а это лишний проход по таблице, пусть и не полный. Зато "процедурно" вполне можно уложиться тоже в 1 проход (и даже не "полный" для задачи "список номеров для групп меньше N элементов").


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
Впервые прочитав вопрос, сразу подумал об окнах.
Потом дошло, что таблицы фокса.
Igor Korolyov
Они не сильно помогут в плане "получения количеств"
Даж не знаю что сказать, может в оракле, такие убогие функции работ с окнами, что то не верится.
Задача элементарно решается...
Только все пустое, у ТС фокс.
ЗЫ. Вообще, как клиент, фокс, ну ни разу не уступит ни кому (ежели не сильно замороченный UI)
А вот данные на нем держать, по мне так куча гимора...


------------------
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Аспид
Даж не знаю что сказать, может в оракле, такие убогие функции работ с окнами, что то не верится.
Задача элементарно решается...
Для получения "количества по группам" оконные функции не нужны. Это тривиальная задача и тривиальный запрос. Достаточно полного прохода по индексу группировочного поля (предполагая что оно не может содержать null-ов, ну или индекс более сложный, включающий в любом случае непустые поля).
Вот для получения "списка элементов из групп содержащих более/менее N элементов" - там уже хорошо применимы оконные/аналитические функции - для того чтобы за один проход и сами элементы извлечь, и просчитать число элементов в группе, дабы ненужные группы отбросить. Без аналитики это подзапрос как в фоксе - он посчитает количества (а это полный проход по индексу, а то и самой таблице), потом выкинет неподходящие группы, и ещё раз пройдясь по таблице (возможно с помощью индекса) получит сами элементы.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Igor Korolyov
Без аналитики это подзапрос как в фоксе - он посчитает количества (а это полный проход по индексу, а то и самой таблице), потом выкинет неподходящие группы, и ещё раз пройдясь по таблице (возможно с помощью индекса) получит сами элементы.
В данном случае индекс по NG (
INDEX ON NG TAG NG
) не участвует в оптимизации (как показывает SYS(3054,12)). Значит нет смысле его делать, если использовать все же SQL-запрос для получения списка групп?
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
VeterVFP
В данном случае индекс по NG (
INDEX ON NG TAG NG
) не участвует в оптимизации (как показывает SYS(3054,12)). Значит нет смысле его делать, если использовать все же SQL-запрос для получения списка групп?
Индекс не используется для подсчёта количества записей в группах. Просто потому что фокс не работает "только по индексу", а значит полного просмотра таблицы не избежать.
Но для получения "списка элементов в подошедших группах" потом (вторым запросом, или внешней частью одного, если их всё же объединить) он вполне себе используется.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Igor Korolyov
Но для получения "списка элементов в подошедших группах" потом (вторым запросом, или внешней частью одного, если их всё же объединить) он вполне себе используется.
Попробовал удалить индекс - начинает использовать для объединения временный (using temp). Значит нет смысла нагружать лишним индексом на десятки млн записей или временный работать будет медленнее?

Upd. И есть ли разница в скорости работы при 2х отдельных запросах и объединении их в один большой?
SELECT Sp.*,Gr.Qnt;
FROM Spisok Sp;
INNER JOIN (SELECT NG, COUNT(NG) Qnt FROM Spisok GROUP BY NG HAVING Qnt<=nInGrQnt) Gr ON Sp.NG=Gr.NG;
ORDER BY Gr.Qnt;
INTO CURSOR ResCurs



Исправлено 1 раз(а). Последнее : VeterVFP, 29.01.18 14:51
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Кому как не тебе, на реальных данных, проще всего измерить время работы разных вариантов
Только учти что для надёжности следует повторять каждое измерение раз по 5-10, и брать среднее. Первый, "холодный" прогон всегда будет заметно медленнее - потому стоит и порядок запуска вариантов менять, ну или хотя бы CLOSE ALL и SYS(1104) использовать... Или просто не учитывать первый результат - но это годится если сама задача состоит в многократном запуске запроса, а не в единичном его прогоне

P.S. Если всё же задача стоит как "получить список элементов для групп из < N элементов", то можно попробовать написать процедурный вариант - ему как раз индекс будет абсолютно необходим С его помощью будет происходить "проскакивание" через ненужные блоки записей из "неподошедших" групп.
В зависимости от статистического распределения данных этот вариант может оказаться на порядки быстрее. Скажем если из твоих 10 Млн записей существует 100тыс групп, а "мелких" (удовлетворяющих ограничению) среди них всего 5 штук, то процедурный вариант будет просто таки "летать" - конечно же при правильном его написании...

P.P.S. Индекс по группировочному полю, в зависимости от самих данных, может оказаться ну ОЧЕНЬ компактным. Основные затраты при этом (на индекс) - операции модификации данных - они будут несколько замедлены (т.к. надо помимо самой dbf ещё и в cdx кое что прописать). Опять же ПРАКТИЧЕСКАЯ выгода от индекса может быть оценена исключительно тестом на живых данных. "Теоретически" он выгоден - но это "сферический конь в вакууме".


------------------
WBR, Igor




Исправлено 2 раз(а). Последнее : Igor Korolyov, 29.01.18 15:30
Ratings: 0 negative/0 positive
Re: Кол-во записей в группе (оптимизация)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Понял
А про использование временного индекса?
VeterVFP
Значит нет смысла нагружать лишним индексом на десятки млн записей?
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 21 (Гостей: 21)

© 2000-2024 Fox Club 
Яндекс.Метрика