powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Порезать большую табличку на json'ы
11 сообщений из 11, страница 1 из 1
Порезать большую табличку на json'ы
    #39954700
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги, приветствую!

Утупился в такую задачку, не могу нормально решить полдня, хоть убейся!
Есть довольно длинная, в пределе - миллиард записей (чуток меньше, но не сильно) таблица.
С PK и кластерным индексом по нему, если это важно.

Нужно получить выборку такого вида:
Номер порции, JSON 100000 (ста тысяч) записей.

Т.е. порезать таблицу на кусочки сто тысяч записей, сделать из каждой порции JSON, и, соответственно вернуть выборку № порции - json.
Принцип отбора записей в порцию - никакого значения не имеет. Ну, разумеется 1 запись должна входить только в одну порцию, и каждая запись должна входить хоть в какую-нибудь порцию.

Как это сделать максимально быстро, с минимумом самосоединений?
Или лучше вообще без них...
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954739
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
WITH N100 AS 
( -- цифры от 0 до 99
	SELECT 0 AS N
	UNION ALL 
	SELECT N100.N + 1 FROM N100
	WHERE N100.N < 99
), -- цифры от 0 до 9999
N10000 AS 
(
	SELECT N = N1.N * 100 + N2.N FROM N100 N1, N100 N2
)
SELECT N1.N100, 
	(SELECT N2.N FROM N10000 N2 WHERE N2.N / 100 = N1.N100 FOR JSON AUTO) AS JSON100
FROM (SELECT DISTINCT  N1.N / 100 AS N100 FROM N10000 N1) N1 
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954761
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

таблицу можно разметить ранжирующей функцией NTILE. Чтобы не активировать сортировку, можно использовать трюк с ORDER BY (1/0).

Код: sql
1.
select ntile(10) over (order by (1/0)) NN, * from dbo.MyTable1
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954766
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Курсор с аккумулированием порции во временную таблицу (табличную переменную) с последующим заджсониванием.
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954771
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

нууу 10к итераций... Зато по разметке можно параллельный джейсонизатор замутить, на сколько ядер хватит.
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954791
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав Колосов
нууу 10к итераций...
Каких итераций? Просто тупой перебор всех строк в цикле.
Владислав Колосов
Зато по разметке можно параллельный джейсонизатор замутить, на сколько ядер хватит.
Что бы что-нибудь запустить по разметке, надо из этой разметки выделить нужные данные. Как выделять будете из вашего примера?
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954808
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, Да, примерно так и делал:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
;

WITH part
AS (
	SELECT a.[regstamp]
		,a.[ID]
		,a.[f1]
		,a.[f2]
		,a.[f3]
		,a.[f4]
		,a.[f5]
		,ROW_NUMBER() OVER (
			ORDER BY 1 / 0
			) / 100000 + 1 [N]
	FROM [act] a
	)
	,N
AS (
	SELECT DISTINCT N
	FROM part
	)
SELECT N.N
	,t.j
FROM N
CROSS APPLY (
	SELECT a.[regstamp]
		,a.[ID]
		,a.[f1]
		,a.[f2]
		,a.[f3]
		,a.[f4]
		,a.[f5]
	FROM part a
	WHERE N.N = a.N
	FOR json path
	) t(j)


Но работает жутко медленно, честно говоря.
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954812
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm
Владислав Колосов
нууу 10к итераций...
Каких итераций? Просто тупой перебор всех строк в цикле.
Владислав Колосов
Зато по разметке можно параллельный джейсонизатор замутить, на сколько ядер хватит.
Что бы что-нибудь запустить по разметке, надо из этой разметки выделить нужные данные. Как выделять будете из вашего примера?

Блин. 800 миллионов строк перебирать в цикле офонареешь.

Теоретически, можно было бы сделать:
Код: sql
1.
2.
3.
4.
5.
6.
insert into #tmp(j)
Select * from [act] a
Order by ID
OFFSET @i*100000 ROWS 
   FETCH NEXT 100000 ROWS ONLY
for json path


Курсором.
Благо это хранилище и данные неизменны.

Может, действительно быстрее получится.
Проблема в том, что ID - GUID.
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954819
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
Блин. 800 миллионов строк перебирать в цикле офонареешь.
А ранжировать и потом селфджойнить не офонареешь? :)

Курсором делается в один проход по таблице. Курсор должен быть fast_forward.
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954823
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm
uaggster
Блин. 800 миллионов строк перебирать в цикле офонареешь.
А ранжировать и потом селфджойнить не офонареешь? :)

Курсором делается в один проход по таблице. Курсор должен быть fast_forward.

Да, так получилось гораздо быстрее.
В тестовой базе на 10 млн. - 30 секунд против 5 с лишним минут примером выше.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
if Object_id('tempdb..#t') is not null
Drop table #t

Create table #t(N int identity(1,1), j nvarchar(max))

declare @i int
Declare part cursor local FORWARD_ONLY READ_ONLY 
for
	SELECT DISTINCT N = number
	FROM master..[spt_values]
	WHERE number >= 0
	and number <= (Select count(*) / 100000 + 1 from [act])

OPEN part  
  
FETCH NEXT FROM part INTO @i 
  
WHILE @@FETCH_STATUS = 0  
BEGIN  

insert into #t(j)
Select * from
(
	SELECT a.[regstamp]
		,a.[ID]
		,a.[f1]
		,a.[f2]
		,a.[f3]
		,a.[f4]
		,a.[f5]
	FROM [act] a
ORDER by a.ID
OFFSET @i*100000 ROWS 
   FETCH NEXT 100000 ROWS ONLY
for json path
) t(j)

FETCH NEXT FROM part INTO @i   
END   
CLOSE part;  
DEALLOCATE part;  



Спасибо, invm , как всегда - выручаете.
(вместо spt_values будет честный генератор миллиона последовательных значений, так что ошибки нет. Это просто для теста).
...
Рейтинг: 0 / 0
Порезать большую табличку на json'ы
    #39954933
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm
Владислав Колосов
нууу 10к итераций...
Каких итераций? Просто тупой перебор всех строк в цикле.
Владислав Колосов
Зато по разметке можно параллельный джейсонизатор замутить, на сколько ядер хватит.
Что бы что-нибудь запустить по разметке, надо из этой разметки выделить нужные данные. Как выделять будете из вашего примера?


По ключам, как же еще? Вы решите задачу перебором строк из рекордсета, а у меня - одновременные просмотры диапазонов ключа. Let's challenge!
Для разовой задачи мое решение избыточно сложное.

PS Это если для сортировки использовать ключ.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Порезать большую табличку на json'ы
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]