БОЛЬШАЯ ВСТАВКА не работает хорошо - PullRequest
1 голос
/ 28 апреля 2020

В моем сценарии мне нужно записать 100 миллионов строк из файлов различного размера на сервер SQL с удаленной машины (в той же сети). Для повышения производительности я уже записываю файлы данных в формате CSV на диск моего компьютера SQL (Y :). Это фрагмент одного из файлов, которые я пытаюсь импортировать

786,166537,46,928024944,23224244.87759578,0.00000021
785,166537,46,923850272,15364.87759500,0.00100000
...

И это MyTable

CREATE TABLE [dbo].[MyTable](
    [Id] [int] NOT NULL,
    [Number1] [int] NOT NULL,
    [Number2] [int] NOT NULL,
    [BigNumber] [bigint] NOT NULL,
    [DecimalNumber] [decimal](26, 8) NOT NULL,
    [NullableDecimal] [decimal](26, 8) NULL
)

Примечание: NullableDecimal имеет значение nullable, но всегда определяется как 0.0 когда пусто Кроме того, в таблице нет индекса.

После перемещения файла на сервер SQL я вызываю эту процедуру, передавая полные пути файла CSV и файла формата:

CREATE PROCEDURE usp_bulk_insert
@bcp_file AS NVARCHAR(200),
@format_file AS NVARCHAR(200)
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @sql NVARCHAR(4000) = 'BULK INSERT dbo.MyTable 
            FROM''' + @bcp_file + ''' 
            WITH 
          (
            FORMATFILE = ''' + @format_file + ''',
            TABLOCK
          );';
    EXEC(@sql);
END

EXEC usp_bulk_insert @bcp_file='Y:\bcp\test.csv', @format_file='Y:\fmt\format_file.xml'

Я также определил файл формата XML, чтобы помочь

<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RECORD>
  <FIELD ID="1" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="12"/>
  <FIELD ID="2" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="12"/>
  <FIELD ID="3" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="12"/>
  <FIELD ID="4" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="21"/>>
  <FIELD ID="5" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="41"/>
  <FIELD ID="6" xsi:type="CharTerm" TERMINATOR="\n" MAX_LENGTH="41"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="Id" xsi:type="SQLINT"/>
  <COLUMN SOURCE="2" NAME="Number1" xsi:type="SQLINT"/>
  <COLUMN SOURCE="3" NAME="Number2" xsi:type="SQLINT"/>
  <COLUMN SOURCE="4" NAME="BigNumber" xsi:type="SQLBIGINT"/>
  <COLUMN SOURCE="5" NAME="DecimalNumber" xsi:type="SQLDECIMAL" PRECISION="26" SCALE="8"/>
  <COLUMN SOURCE="6" NAME="NullableDecimal" xsi:type="SQLDECIMAL" PRECISION="26" SCALE="8"/>
 </ROW>
</BCPFORMAT>

Независимо от того, что я пытаюсь, мне кажется, что я не могу сделать лучше, чем 30 секунд для файла 300Mb с 3 миллионов строк.

Я попробовал несколько советов с этого сайта ; рекомендуется использовать локальные именованные каналы, я пытался, и я не мог найти слишком много информации об этом. Есть ли что-нибудь, что я могу попытаться сделать лучше?

---------- РЕДАКТИРОВАТЬ

Я запускаю команду BULK INSERT в новом сеансе и запускаю команду

select * from sys.dm_exec_session_wait_stats order by wait_time_ms desc 

Здесь верх 10 результатов:

session_id  wait_type   waiting_tasks_count wait_time_ms
75  SOS_SCHEDULER_YIELD 7107    206
75  MEMORY_ALLOCATION_EXT   38934   111
75  PREEMPTIVE_OS_WRITEFILE 528 65
75  IMPPROV_IOWAIT  6   44
75  PAGEIOLATCH_EX  2   20
75  PREEMPTIVE_OS_CREATEFILE    10  7
75  WRITELOG    1   3
75  PREEMPTIVE_OS_FILEOPS   4   2
75  PAGEIOLATCH_UP  1   1

Я буду исследовать их!

---------- РЕДАКТИРОВАТЬ

У меня есть полный контроль над созданием файл, который я не могу изменить, это формат финальной таблицы

Remote Scan Table Insert

...