marcioe Posted May 2, 2016 Report Share Posted May 2, 2016 Amigos estou tendo problemas para criar um campo novo em uma tabela com mais de 5 milhões de registros. Faço mais ou menos assim. ALTER TABLE ctrc_nf ADD campo char(80) not null AFTER fone; Daí demora demais mais de uma hora. O servidor e Linux, e é xeon biprocessado. Com discos SAS, etc. Será que tem como melhorar isso. Quote Link to comment Share on other sites More sharing options...
Ariston Santos Posted May 2, 2016 Report Share Posted May 2, 2016 Não sei se funciona, mas você pode tentar assim: • Criar um a tabela temporária com a nova estrutura; • Dar um INSERT INTO tabela_temp (Campo1, Campo2, ...) SELECT Campo1, Campo2, ... FROM tabela_atual • Dar um DROP TABLE na tabela atual • Dar um ALTER TABLE tabela_temp RENAME tabela_atual Este é o método que uso atualmente para modificar estrutura de tabelas, mas ainda não testei com tabelas com grande quantidade de arquivos. Também ainda não testei em ambiente multi-usuário. Segue o código que uso, para você ter uma ideia. Eu uso a SQLRDD. Criação de uma tabela: // Criação da tabela de itens por revendedora: gas_itens aEstr:={} AADD( aEstr ,{ "cnpjid", "C", 14, 0 } ) // Revendedor: CNPJ da disk gás/água AADD( aEstr ,{ "itemid", "C", 13, 0 } ) // Item: Código pessoal - pode ser o código de barras do cliente. AADD( aEstr ,{ "itdesc", "C", 50, 0 } ) // Item: Descrição AADD( aEstr ,{ "itprun", "N", 10, 2 } ) // Item: Valor unitário AADD( aEstr ,{ "ittaxa", "N", 10, 2 } ) // Item: Taxa de entrega AADD( aEstr ,{ "itfoto", "M", 10, 0 } ) // Item: Imagem do item AADD( aEstr ,{ "itmobs", "C",100, 0 } ) // Item: Observação IF ! SR_ExistTable( "gas_itens" ) TRY cComm := XB2SqlStr(aEstr, "gas_itens") nErr := oSql:Execute( cComm ) CATCH oErr MsgAlert("Erro ao tentar conectar com o banco de dados."+CRLF+; "Favor verificar sua conexão e tente novamente."+CRLF+CRLF+; "Erro: "+oErr:Description, "Ocorreu um erro") FileWrite(ErroFile(), oErr:Description) PostQuitMessage( 0 ) __QUIT() END else lChg := ChkStruct("gas_itens", "", aEstr, oSql, nErr, nPos) ENDIF A função XB2SqlStr() STATIC FUNCTION XB2SqlStr(aStr, cDBase) LOCAL cStrct cStrct := "CREATE TABLE `"+LOWER(cDBase)+"` (" FOR nF := 1 TO LEN(aStr) IF LOWER(aStr[nF,1]) != "sr_recno" IF nF > 1 ; cStrct += ", " ; ENDIF // Mais de um campo cStrct += "`"+LOWER(aStr[nF,1])+"` "+SetFType(aStr[nF,2],aStr[nF,3],aStr[nF,4]) ENDIF NEXT IF LEN(aStr) > 0 ; cStrct += ", " ; ENDIF // Já acrescentado algum campo cStrct += "`sr_recno` BIGINT (15) NOT NULL UNIQUE AUTO_INCREMENT)" // Sempre criar o 'sr_recno' no final, para compatibilizar com SQLRDD RETURN( cStrct ) STATIC FUNCTION SetFType(cTipo,nSize,nDeci) LOCAL cFType IF cTipo = "C" ; cFType := "char("+ALLTRIM(STR(nSize))+")" ELSEIF cTipo = "M" ; cFType := "mediumblob" ELSEIF cTipo = "N" ; cFType := "double("+ALLTRIM(STR(nSize))+","+ALLTRIM(STR(nDeci))+")" ELSEIF cTipo = "L" ; cFType := "tinyint(4)" ELSEIF cTipo = "D" ; cFType := "date" ENDIF RETURN(cFType) A função que faz a modificação na estrutura, se necessário: ChkStruct() STATIC FUNCTION ChkStruct(cTable, cUniq, aStrct, oSql, nErr, nPos) LOCAL lChangd, cComm, aNewStr, aOldStr, aChange, aImport, cImport, aArray := {}, cTmpTable := cTable+"_old" aNewStr := aStrct nScan := ASCAN(aNewStr, {|nC|nC[1]="sr_recno"}) IF nScan = 0 AADD(aNewStr, {"sr_recno", "N", 15, 0}) // SQLRDD acrescenta este campo ao criar a tabela ENDIF cSay := "Verificando a tabela '"+cTable+"'" oSay:SetText(cSay) oSay:Refresh() IF ! l_Check ; RETURN .F.; ENDIF // Obter a estrutura da tabela atual. nErr := 0 TRY cComm := "SELECT * FROM "+cTable+" LIMIT 1" nErr := oSql:Execute( cComm ) oSql:iniFields(.f.) aOldStr := oSql:aFields // Para pegar a estrutura CATCH ShowMsgTray("Não foi possível testar a tabela '"+cTable+"'", "Aguarde...") ; SysWait(1) RETURN .F. END TRY // Comparar com a estrutura de aStrct lChangd := .F. aChange := {} aImport := {} cImport := "" TRY FOR nX := 1 TO LEN(aNewStr) // Verifica se foi acrescentado algum campo ou se mudou o tamanho de algum. cFild:=Lower(aNewStr[nX,1]) cType:=aNewStr[nX,2] cSize:=STRZERO(aNewStr[nX,3], 4) cDeci:=STRZERO(aNewStr[nX,4], 3) nElem := ASCAN(aOldStr, {|aNro| Lower(aNro[1]) == cFild}) IF nElem > 0 if cFild != "sr_recno" // Não considerar erro de estrutura deste IF cType != aOldStr[nElem,2] .OR. ; cSize != STRZERO(aOldStr[nElem,3], 4) .OR. ; cDeci != STRZERO(aOldStr[nElem,4], 3) lChangd := .T. // Mudou o tamanho de um campo aadd(aChange, {cFild, "Modificou a estrutura"}) ENDIF endif ELSE lChangd := .T. // Foi removido algum campo aadd(aChange, {cFild, "Campo acrescentado"}) ENDIF NEXT FOR nX := 1 TO LEN(aOldStr) // Verifica se foi excluindo algum compo cFild := Lower(aOldStr[nX,1]) nElem := ASCAN(aNewStr, {|aNro| Lower(aNro[1]) == cFild}) IF nElem = 0 lChangd := .T. // Algum campo foi removido aadd(aChange, {cFild, "Campo removido"}) ELSE AADD(aImport, cFild) // Para pegar só os campos que existem nas duas tabelas. ENDIF NEXT IF lChangd // Determinar quais campos serão importados da tabela temporária FOR nX := 1 TO LEN(aImport) IF Lower(aImport[nX]) != "sr_recno" // Apenas um teste IF ! EMPTY(cImport) ; cImport += ", " ; ENDIF cImport += Lower(aImport[nX]) // Pegar só os campos que existem nas duas tabelas. ENDIF NEXT ENDIF CATCH ShowMsgTray("Não foi possível testar a tabela '"+cTable+"'", "Aguarde...") SysWait(0.5) RETURN .F. END TRY IF SR_ExistTable( cTmpTable ) cComm := "DROP TABLE "+cTmpTable TRY nErr := oSql:Execute( cComm ) if nErr == 0 ShowMsgTray("Executou "+cComm, "Ok") ; SysWait(0.5) else ShowMsgTray("Não foi preciso executar "+cComm, "Aguarde...") ; SysWait(2) endif CATCH ShowMsgTray("Não foi possível excluir a tabela '"+cTmpTable+"'", "Erro...") SysWait(0.5) RETURN .F. END TRY ENDIF IF ! lChangd ShowMsgTray("Extrutura de '"+cTable+"' sem alterações.", "Ok") ; SysWait(0.5) RETURN .F. ENDIF // Ver se tem itens na tabela oSql:Exec("SELECT * FROM "+cTable,,.t.,@aArray,,,0) cComm := "ALTER TABLE "+cTable+" RENAME "+cTmpTable nErr := oSql:Execute( cComm ) if nErr == 0 ShowMsgTray("Executou "+cComm, "Ok") ; SysWait(0.5) else ShowMsgTray("Não foi possível executar "+cComm, "Aguarde...") ; SysWait(2) RETURN .F. endif l_Err := .F. TRY cComm := XB2SqlStr(aStrct, cTable) nErr := oSql:Execute( cComm ) ShowMsgTray("Criou "+cTable, "Ok") ; SysWait(0.5) CATCH oErr FileWrite(ErroFile(), oErr:Description) l_Err := .T. END TRY IF l_Err cComm := "ALTER TABLE "+cTmpTable+" RENAME "+cTable nErr := oSql:Execute( cComm ) ShowMsgTray("Erro ao tentar criar a nova a tabela: Executado RollBack '"+cTable+"'.","Erro") ; SysWait(1) RETURN .F. ENDIF IF ! EMPTY(cUniq) TRY cSql := "ALTER TABLE "+cTable+" ADD UNIQUE ("+cUniq+")" nErr := oSql:Execute(cSql) ShowMsgTray("Executada query "+cSql,"Retorno: "+cValToChar(nErr)) ; SysWait(1) CATCH END TRY ENDIF // Importar dados da tabela temporária IF LEN(aArray) > 0 TRY cQury := "INSERT INTO "+cTable+" ("+cImport+") SELECT "+cImport+" FROM "+cTmpTable BEGIN TRANSACTION nErr := oSql:Execute(cQury) END TRANSACTION oSql:Commit() ShowMsgTray("Executou "+cComm, "Ok") ; SysWait(0.5) CATCH oErr MsgAlert("Erro ao tentar conectar com o banco de dados."+CRLF+; "Favor verificar sua conexão e tente novamente."+CRLF+CRLF+; "Erro: "+oErr:Description, "Ocorreu um erro") FileWrite(ErroFile(), oErr:Description) END TRY ENDIF // Excluir a tabela temporária cComm := "DROP TABLE "+cTmpTable nErr := oSql:Execute( cComm ) if nErr == 0 ShowMsgTray("Executou "+cComm, "Ok") ; SysWait(0.5) else ShowMsgTray("Não foi preciso executar "+cComm, "Aguarde...") ; SysWait(2) endif RETURN( .t. ) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.