我们需要使用 Oracle 8i 在表中插入大约 250,000-500,000 行的大行。有 3 列,每列仅包含 3 个字符。我编写了一个简单的 shell 脚本,因此我们有一个本地 Oracle 19c DB,它在大约 1 到 2 分钟内完成插入。(使用 Sql*Loader 不是我们的选择)
现在的问题是我需要插入的实际数据库是 Oracle 8i。我正在使用完全相同的脚本。即使插入 10000 条记录也需要花费大量时间。我发现以目前的速度,同样的过程将需要大约 8 个小时。出了什么问题?我该如何优化它。了解 Oracle 的版本是否负责或其他原因会很有帮助。我尝试过使用差异大小(如 200,500,1000 等)的批量插入,但没有帮助。批量插入在 Oracle 8i 中没有帮助吗?事实上,批量插入使得 19c 的速度大大加快。
编辑:我正在添加我正在使用的 shell 脚本,在 19c 中插入 1000 条记录只需半秒,但相同的脚本需要几分钟,而实际记录则需要几个小时。所以我从 db1 获取记录并将其插入到 db2。 TEMP_SQL_FILE 的目的也是收集 1000 个插入命令作为文件中的字符串。 BATCH_SIZE=50 帮助我收集 50 个这样的插入字符串并将其放入文件中。所以最终,1000
INSERT INTO TABLE2 (USERID, SALARY, ZIP) VALUES ('$USERID', '$SALARY', '$ZIPCODE');
将收集在临时文件中,然后通过 sql plus 插入。
#!/bin/ksh
# DB1 (source database) details (**19c**)
DB1_USER="user1"
DB1_PASSWORD="pwd1"
DB1_DB=db1.abc.com
# DB2 (destination database) connection details (**8i**)
DB2_USER="user2"
DB2_PASSWORD="pwd2"
DB2_DB=db2.xyz.com
# Temporary file to hold SQL commands
TEMP_SQL_FILE="batch_inserts.sql"
BATCH_SIZE=50 # Number of records to accumulate before writing to file
COMMIT_THRESHOLD=1000 # Number of records after which to commit
counter=0 # To keep track of total records written
batch_counter=0 # To track batch size
sql_batch=""
# SQL Query to fetch data from DB1 table1 table
SQL_QUERY="SELECT userid || '|' || salary || '|' || zip FROM table1;"
# Fetch data from DB1 and insert into DB2
sqlplus -s "$DB1_USER/$DB1_PASSWORD@$DB1_DB" <<EOF | while IFS='|' read -r USERID SALARY ZIPCODE
SET HEADING OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SET LINESIZE 1000
$SQL_QUERY
EXIT;
EOF
do
# Accumulate SQL insert statements in the batch variable
sql_batch+="INSERT INTO TABLE2 (USERID, SALARY, ZIP) VALUES ('$USERID', '$SALARY', '$ZIPCODE');\n"
((batch_counter++))
((counter++))
# Check if we reached the batch size, then write to file
if [ "$batch_counter" -ge "$BATCH_SIZE" ]; then
echo -e "$sql_batch" >> "$TEMP_SQL_FILE"
sql_batch="" # Clear the batch variable
batch_counter=0 # Reset the batch counter
fi
# Check if we reached the commit threshold
if [ "$counter" -ge "$COMMIT_THRESHOLD" ]; then
# Execute the SQL batch
sqlplus -s "$DB2_USER/$DB2_PASSWORD@$DB2_DB" <<EOF
@$TEMP_SQL_FILE
COMMIT;
EXIT;
EOF
# Clear the temporary file after commit
> "$TEMP_SQL_FILE"
counter=0 # Reset the counter after commit
fi
done
# Final commit for any remaining records
if [ -n "$sql_batch" ]; then
echo -e "$sql_batch" >> "$TEMP_SQL_FILE"
fi
if [ -s "$TEMP_SQL_FILE" ]; then
sqlplus -s "$DB2_USER/$DB2_PASSWORD@$DB2_DB" <<EOF
@$TEMP_SQL_FILE
COMMIT;
EXIT;
EOF
fi
# Clean up
rm "$TEMP_SQL_FILE"
尝试以下方法(步骤在一个会话中执行):
第1步:
ALTER SESSION SET skip_unusable_indexes = true;
第 2 步: 禁用索引
ALTER INDEX index_name UNUSABLE;
第 3 步: 导入
第4步:重建索引
ALTER INDEX index_name REBUILD [ONLINE];