Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / И снова здравствуйте, Оптимизация. / 8 сообщений из 8, страница 1 из 1
22.03.2018, 18:15
    #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
22.03.2018, 19:12
    #39619121
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И снова здравствуйте, Оптимизация.
minya13_85,

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

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

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

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

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

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


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