powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / И снова здравствуйте, Оптимизация.
8 сообщений из 8, страница 1 из 1
И снова здравствуйте, Оптимизация.
    #39619096
minya13_85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть табличка остатки, там пишется движение по каждому штрихкоду, как он двигался с одного склада на другой или был отгружен клиенту.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE TABLE [dbo].[ostatki](
	[code] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
	[identifier] [nvarchar](20) NOT NULL,
	[docID] [int] NULL,
	[motion] [smallint] NULL,
	[lineID] [smallint] NULL,
	[skladID] [smallint] NULL,
	[masterID] [int] NULL,
	[stateID] [smallint] NULL,
	[dateOut] [smalldatetime] NULL,
	[deleted] [smallint] NULL,
	[rowguid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
 CONSTRAINT [PK_ostatki] PRIMARY KEY CLUSTERED 
(
	[code] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO



В Этой таблице 109 млн записей и два индекса:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
CREATE NONCLUSTERED INDEX [IX_deleted] ON [dbo].[ostatki]
(
	[deleted] ASC
)
INCLUDE ( 	[identifier],
	[docID],
	[motion],
	[masterID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]



CREATE NONCLUSTERED INDEX [IX_identifier] ON [dbo].[ostatki]
(
	[identifier] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO



Есть табличка справочник складов компании она просто таблица без индексов там 120 записей
Код: sql
1.
2.
3.
4.
5.
CREATE TABLE [dbo].[M_SKLAD](
	[OrgID] [int] NULL,
	[sklad] [nvarchar](20) NULL,
	[masterID] [int] NULL
) ON [PRIMARY]



Есть табличка фирмы, там более укрупненное название складов. В этой таблице 10 тыщ записей
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE TABLE [dbo].[firmName](
	[code] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
	[FirmName] [nvarchar](50) NOT NULL,
	[inn] [nvarchar](15) NULL,
	[FirmID] [int] NOT NULL,
	[globalID] [int] NOT NULL,
 CONSTRAINT [PK_firmName] PRIMARY KEY NONCLUSTERED 
(
	[code] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [IX_firmName_1] UNIQUE NONCLUSTERED 
(
	[FirmName] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]



Там есть 1 индекс
Код: sql
1.
2.
3.
4.
5.
CREATE UNIQUE CLUSTERED INDEX [IX_firmName] ON [dbo].[firmName]
(
	[FirmID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO



Есть таблица с датами по документу, в этой таблице 2 млн записей
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE TABLE [dbo].[docsDate](
	[docCreateDate] [smalldatetime] NULL,
	[docExecuteDate] [smalldatetime] NULL,
	[docPrintDate] [smalldatetime] NULL,
	[docID] [int] NULL,
	[code] [int] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_docsDate] PRIMARY KEY NONCLUSTERED 
(
	[code] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]



Там есть 3 индекса
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE UNIQUE CLUSTERED INDEX [IX_docsDate] ON [dbo].[docsDate]
(
	[docID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [NCI_docprintdate] ON [dbo].[docsDate]
(
	[docPrintDate] ASC
)
INCLUDE ( 	[docID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO


CREATE NONCLUSTERED INDEX [IX_docexecutedate] ON [dbo].[docsDate]
(
	[docExecuteDate] ASC
)
INCLUDE ( 	[docID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO



Я просчитываю остаток, какие штрихкоды находились на складах компании на заданную дату.
Код: 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.
DECLARE @d smalldatetime
set dateformat dmy
set @d='07-03-2018'


CREATE TABLE #tbl (masterID int PRIMARY KEY,globalID int)
INSERT INTO #tbl(masterID,globalID)
select masterID,f.globalID 
from Accounting.dbo.M_SKLAD as s
LEFT join Attrib.dbo.firmname as f with(nolock) on s.masterid = f.firmid



SELECT  o.identifier,MAX(1000000000*convert(bigint,o.docID)+(case when o.motion=1 then o.masterID else 0 end))-1000000000*convert(bigint,MAX(o.docID)) as masterid
FROM #tbl as t with(nolock)
LEFT join main.dbo.ostatki as o with(nolock) on t.masterID=o.masterID
LEFT JOIN mainex.dbo.docsDate with(nolock) on docsDate.docid=o.docid
where o.deleted=0 and docsDate.docExecuteDate<@d  
group by o.identifier,t.globalID
having sum(o.motion)=1 
and MAX(1000000000*convert(bigint,o.docID)+(case when o.motion=1 then o.masterID else 0 end))-1000000000*convert(bigint,MAX(o.docID))<>0

option(recompile)


drop table #tbl



По коду поясняю, это длинная конструкция
Код: sql
1.
MAX(1000000000*convert(bigint,o.docID)+(case when o.motion=1 then o.masterID else 0 end))-1000000000*convert(bigint,MAX(o.docID))


нужна для того чтобы убрать пропуски, нарушена целостность базы, некоторые движений внутри складов нету в таблице, сейчас приведу небольшой пример как обстоят таблицы
Код: 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.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
SET NOCOUNT ON
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO


IF OBJECT_ID('[TestDoc].[Ostatki]') IS NOT NULL
  DROP TABLE [TestDoc].[Ostatki]

IF OBJECT_ID('[TestDoc].[M_SKLAD]') IS NOT NULL
  DROP TABLE [TestDoc].[M_SKLAD]

IF OBJECT_ID('[TestDoc].[firmname]') IS NOT NULL
  DROP TABLE [TestDoc].[firmname]

IF OBJECT_ID('[TestDoc].[docsdate]') IS NOT NULL
  DROP TABLE [TestDoc].[docsdate]

IF SCHEMA_ID('TestDoc') IS NULL
  EXEC('
    CREATE SCHEMA [TestDoc]
  ')
GO

IF OBJECT_ID('[TestDoc].[Ostatki]') IS NULL
  
CREATE TABLE [TestDoc].[Ostatki]
  (
    [code]        Int           NOT NULL  IDENTITY(1,1),
	[identifier] nvarchar(50) NOT NULL,
	[docid] [int] NULL,
    [motion] [smallint] NULL,
	[masterID] [int] NULL,
	[dateOut] [smalldatetime] NULL,
	[deleted] [smallint] NULL,
   PRIMARY KEY CLUSTERED([code])
  )
GO


IF OBJECT_ID('[TestDoc].[M_SKLAD]') IS NULL
  
CREATE TABLE [TestDoc].[M_SKLAD]
  (
    [OrgID] [int] NULL,
	[sklad] [nvarchar](20) NULL,
	[masterID] [int] NULL
  )
GO


IF OBJECT_ID('[TestDoc].[firmname]') IS NULL
  
CREATE TABLE [TestDoc].[firmname]
  (
    [code] [int] NOT NULL  IDENTITY(1,1),
	[FirmName] [nvarchar](50) NOT NULL,
	[inn] [nvarchar](15) NULL,
	[FirmID] [int] NOT NULL,
	[globalID] [int] NOT NULL,
	 PRIMARY KEY CLUSTERED([code])
  )
GO



IF OBJECT_ID('[TestDoc].[docsdate]') IS NULL
  
CREATE TABLE [TestDoc].[docsdate]
  (
    [docCreateDate] [smalldatetime] NULL,
	[docExecuteDate] [smalldatetime] NULL,
	[docPrintDate] [smalldatetime] NULL,
	[docID] [int] NULL,
	[code] [int] IDENTITY(1,1) NOT NULL,
 PRIMARY KEY CLUSTERED([code])

  )
GO

INSERT INTO TestDoc.docsdate
select '2017-03-01 10:00:00','2017-03-01 15:00:00','2017-03-01 00:00:00',1
UNION
select '2017-03-02 10:00:00','2017-03-02 15:00:00','2017-03-02 00:00:00',2
UNION
select '2017-03-05 10:00:00','2017-03-05 17:00:00','2017-03-05 00:00:00',3
UNION
select '2017-03-08 10:00:00','2017-03-08 15:00:00','2017-03-08 00:00:00',4
UNION
select '2017-03-02 10:00:00','2017-03-02 15:00:00','2017-03-02 00:00:00',5
UNION
select '2017-03-02 11:00:00','2017-03-02 15:00:00','2017-03-02 00:00:00',6
UNION
select '2017-03-08 10:00:00','2017-03-04 15:00:00','2017-03-04 00:00:00',8
UNION
select '2017-03-05 10:00:00','2017-03-05 15:00:00','2017-03-05 00:00:00',7
UNION
select '2017-03-02 10:00:00','2017-03-02 15:00:00','2017-03-02 00:00:00',9
UNION
select '2017-03-04 10:00:00','2017-03-04 15:00:00','2017-03-04 00:00:00',10
UNION
select '2017-03-08 10:00:00','2017-03-08 15:00:00','2017-03-08 00:00:00',11
UNION
select '2017-03-21 10:00:00','2017-03-22 15:00:00','2017-03-22 00:00:00',12


INSERT INTO [TestDoc].[firmname]
SELECT 'ТД','0101',150,150
UNION
SELECT 'ЮК','0102',110,150
UNION
SELECT 'ПК','0103',130,130


INSERT INTO [TestDoc].[M_SKLAD]
SELECT 1,'СКЛАД10',150
UNION
SELECT 1,'СКЛАД4',110
UNION
SELECT 2,'СКЛАД5',130


INSERT INTO [TestDoc].[Ostatki]

SELECT 'А700',1,-1,100,'2017-03-01 10:00:00',0
UNION
SELECT 'А700',1,1,150,'2017-03-01 10:00:00',0
UNION
SELECT 'А700',2,-1,150,'2017-03-02 11:00:00',0
UNION
SELECT 'А700',2,1,110,'2017-03-02 11:00:00',0
UNION
SELECT 'А700',3,-1,110,'2017-03-05 16:00:00',0
UNION
SELECT 'А700',3,1,130,'2017-03-05 16:00:00',0
UNION
SELECT 'А700',4,-1,130,'2017-03-08 10:00:00',0
UNION
SELECT 'А700',4,1,180,'2017-03-08 10:00:00',0
UNION
SELECT 'А600',5,-1,145,'2017-03-02 10:00:00',0
UNION
SELECT 'А600',5,1,200,'2017-03-02 10:00:00',0
UNION
SELECT 'А600',6,-1,200,'2017-03-02 11:00:00',0
UNION
SELECT 'А600',6,1,150,'2017-03-02 11:00:00',0
UNION
SELECT 'А600',7,-1,130,'2017-03-05 16:00:00',0
UNION
SELECT 'А600',7,1,160,'2017-03-05 16:00:00',0
UNION
SELECT 'А600',8,-1,150,'2017-03-08 10:00:00',0
UNION
SELECT 'А600',8,1,130,'2017-03-08 10:00:00',0
UNION
SELECT 'А800',9,-1,126,'2017-03-02 10:00:00',0
UNION
SELECT 'А800',9,1,110,'2017-03-02 10:00:00',0
UNION
SELECT 'А800',10,-1,150,'2017-03-04 11:00:00',0
UNION
SELECT 'А800',10,1,140,'2017-03-04 11:00:00',0
UNION
SELECT 'А800',11,-1,140,'2017-03-08 16:00:00',0
UNION
SELECT 'А800',11,1,110,'2017-03-08 16:00:00',0
UNION
SELECT 'А800',12,-1,130,'2017-03-22 10:00:00',0
UNION
SELECT 'А800',12,1,190,'2017-03-22 10:00:00',0



Уже очень долгое время бьюсь над оптимизацией данного выше запроса
План запроса прилагаю, закинул в рар, т.к. сам план весит 174 кб, превышает 150
...
Рейтинг: 0 / 0
И снова здравствуйте, Оптимизация.
    #39619121
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
minya13_85,

ничего не сделаете с запросами: или грубой силой - увеличением вычислительной мощности или считайте агрегацию заранее.
Можно секционировать данные в остатках по masterID, если мало складов приходит во временную таблицу и данные об остатках более-менее распределены по ним. Будете просматривать меньший объём в запросе.
...
Рейтинг: 0 / 0
И снова здравствуйте, Оптимизация.
    #39619246
minya13_85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав Колосов,
да вот же заранее не просчитать, это остаток на заданную дату, динамический запрос. Может еще есть варианты? как избавиться от параллелизма этого?
...
Рейтинг: 0 / 0
И снова здравствуйте, Оптимизация.
    #39619822
nvv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
nvv
Гость
minya13_85,
Почему нет?
Учётные системы именно так и делают.
Например хранят рассчитанные остатки на начало каждого месяца. Тогда движений может быть хоть миллиард, а остатков на каждый месяц по разному: где густо, а где и пусто. Таким образом усложняются запросы, но скорость на высоте.
...
Рейтинг: 0 / 0
И снова здравствуйте, Оптимизация.
    #39619851
LSV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я сделал так:

Есть журнал движения (как в сабже) и есть журнал незакрытых партий, т.е. остаток партии без привязок "приход-расход".
Незакрытые партии и есть "остаток на сейчас".
А остаток на любое время это "сумма незакрытых партий" - "обороты от нужной даты до сейчас по журналу движения".

Производительность плавно убывает с удаленностью даты "от сейчас", но старые даты редко нужны.

Такая схема редко требует урезки.

зы: если пришло 10 и ушло 10, то партия исчерпана и ее не нужно считать в остатках.
...
Рейтинг: 0 / 0
И снова здравствуйте, Оптимизация.
    #39619872
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте. Можно задать маленький вопрос чтоб не создавать тему. В MSSQL 2012 есть в таблице некластеризованный индекс из 3х полей, одно из его полей C_Tov не имеет ограничения (NOT NULL). Фактически значений NULL в этом поле нет и не будет. Таблица довольно большая и поле C_Tov участвует во множестве выборок и джоинов. Будет ли лучше для производительности этих запросов если я поставлю на него ограничение NOT NULL?
...
Рейтинг: 0 / 0
И снова здравствуйте, Оптимизация.
    #39620213
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Будет.
...
Рейтинг: 0 / 0
И снова здравствуйте, Оптимизация.
    #39620228
bilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster,

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


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