SQL Server:如何改进插入查询?

问题描述

| 我有一个未规范化的数据库: disciplinabd.movi​​es:
CREATE TABLE dbo.movies
    (
    movieid      VARCHAR (20) NULL,title        VARCHAR (400) NULL,mvyear       VARCHAR (100) NULL,actorid      VARCHAR (20) NULL,actorname    VARCHAR (250) NULL,sex          CHAR (1) NULL,as_character VARCHAR (1500) NULL,languages    VARCHAR (1500) NULL,genres       VARCHAR (100) NULL
    )
我有我的数据库:labbd11,在这里我将规范来自disciplinabd的数据。 因此,我正在尝试执行以下查询:
INTO labbd11..movie_actor(idMovie,idActor,idCharacter) 
SELECT CASE 
         WHEN IsNumeric(movies.movieid+ \'.0e0\') <> 1  THEN NULL 
         ELSE CAST (movies.movieid AS INT) 
       END,CASE WHEN IsNumeric(movies.actorid+ \'.0e0\') <> 1  THEN NULL 
            ELSE CAST (movies.actorid AS INT) 
       END,(SELECT id FROM actor_character WHERE character = movies.as_character) 
FROM disciplinabd..movies
它可以正常执行,但是我需要执行大量数据,例如disciplinabd.movi​​es中的1400万行。 我的问题是: 有如何改善我的插入物? 完成后我可以插入诸如
insert (1,1000) ...
之类的东西吗,我只需更改诸如
insert( 1001,2000) ..
之类的值并继续。 我的意思是,是否有可能一点一点地在数据库中插入? 这样,如果连接断开,我可以避免回滚操作。 昨天,此插入查询运行了16个小时,然后连接中断,我丢失了所有工作。 更新
CREATE TABLE movie(
    id INT PRIMARY KEY,title VARCHAR(400) NOT NULL,year INT
)

CREATE TABLE actor (
    id INT PRIMARY KEY,name VARCHAR(250) NOT NULL,sex CHAR(1) NOT NULL
)

CREATE TABLE actor_character(
    id INT PRIMARY KEY IDENTITY,character VARCHAR(1000)
)

CREATE TABLE movie_actor(
    idMovie INT,idActor INT,idCharacter INT,CONSTRAINT fk_movie_actor_1 FOREIGN KEY (idMovie) REFERENCES movie(id) ON DELETE CASCADE ON UPDATE CASCADE,CONSTRAINT fk_movie_actor_2 FOREIGN KEY (idActor) REFERENCES actor(id) ON DELETE CASCADE ON UPDATE CASCADE,CONSTRAINT fk_movie_actor_3 FOREIGN KEY (idCharacter) REFERENCES actor_character(id) ON DELETE CASCADE ON UPDATE CASCADE,CONSTRAINT pk_movie_actor PRIMARY KEY (idMovie,idCharacter)
)
    

解决方法

您没有看到正在使用的RDBMS,这可能有助于我们更准确地回答您的问题,但是要回答第二个问题,您很可能会限制SELECT查询以影响插入的数据量。例如,
INSERT INTO labbd11..movie_actor(idMovie,idActor,idCharacter) 
SELECT CASE 
         WHEN IsNumeric(movies.movieid+ \'.0e0\') <> 1  THEN NULL 
         ELSE CAST (movies.movieid AS INT) 
       END,CASE WHEN IsNumeric(movies.actorid+ \'.0e0\') <> 1  THEN NULL 
            ELSE CAST (movies.actorid AS INT) 
       END,(SELECT id FROM actor_character WHERE character = movies.as_character) 
FROM disciplinabd..movies
WHERE movieid >= 1000 and movieid < 2000
如果没有连续的ID范围,则可以生成一个ID范围,但是方法将取决于您使用的特定数据库。 至于您最初关于如何提高性能的问题,我将从将子选择移到JOIN并确保actor_character中的索引正确开始。例如:
INTO labbd11..movie_actor(idMovie,actor_character.id 
FROM disciplinabd..movies
LEFT JOIN disciplinabd..actor_characture ON movies.as_character = actor_characture.character
WHERE movieid >= 1000 and movieid < 2000
同样,如果您可以明确说明您使用的是哪个数据库,我们可以提供更多更适合您的答案。如果我正在写类似的东西,我不会期望1400万行在服务器级硬件上执行需要花费几分钟的时间。     ,16小时似乎很长的时间,只能插入1400万行。我不知道您的硬件是什么样的,所以我只会回答眼前的问题。如果有1400万行,则每1000个连接打开一个连接的速度会慢得多,因此我建议使用可变的数字。 如果可以的话,我还建议为movieid添加一个索引。
create nonclustered index IX_movies on movies(movieid)
您可以使用while循环来完成所需的操作。
Declare @loopMax int,@bottomRange int,@topRange int,@rangeSize int
select @loopMax = MAX(movies.movieid) from disciplinabd..movies
set @rangeSize = @loopMax/20
set @bottomRange = 0
set @topRange = @rangeSize
while @topRange < @loopMax
begin
    INSERT INTO labbd11..movie_actor(idMovie,idCharacter) 
    SELECT CASE 
        WHEN IsNumeric(movies.movieid+ \'.0e0\') <> 1  THEN NULL 
        ELSE CAST (movies.movieid AS INT) 
   END,CASE WHEN IsNumeric(movies.actorid+ \'.0e0\') <> 1  THEN NULL 
        ELSE CAST (movies.actorid AS INT) 
   END,actor_character.id 
   FROM disciplinabd..movies
   LEFT JOIN actor_character ON movies.as_character = actor_character.character
   WHERE movieid >= @bottomRange and movieid < @topRange
   set @bottomRange = @topRange
   set @topRange = @topRange + @rangeSize
end    
    

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...