La mejor manera de volver a importar una gran cantidad de datos con un tiempo de inactividad mínimo

11

Necesito importar aproximadamente 500,000 registros que contienen datos de búsqueda de IP (referencia de solo lectura) aproximadamente una vez a la semana (solo tres cols int / bigint).

Realmente no quiero preocuparme por fusionar los datos con la tabla existente, preferiría borrar lo viejo y volver a importar.

Idealmente, las consultas que se ejecutan sobre los datos continuarían ejecutándose (no recibimos muchos de estos y es aceptable que se ejecuten un poco más lento mientras se produce la importación, pero deben estar activos las 24 horas del día, los 7 días de la semana, por lo tanto, ejecute esto " fuera de horario "no es una opción).

Cosas intentadas hasta ahora

SSIS: he creado un paquete SSIS que trunca la tabla y las importaciones; tarda unos 30 segundos en ejecutarse (demasiado tiempo realmente).

Tabla temporal: importar a una tabla temporal, truncar y copiar también demora unos 30 segundos.

BCP: la importación masiva también es bastante lenta (por alguna razón es más lenta que SSIS (incluso sin índices para mantener); supongo que es algo que tiene que ver con las transacciones char-> int / bigint: /

Mesa de espejo? Entonces, en este momento, me pregunto si leer la tabla a través de una vista, importar los datos en una tabla espejo y alterar la vista para apuntar a esta tabla ... parece que será rápido, pero parece pequeño un poco hacky para mi

Parece que debería ser un problema común, pero no puedo encontrar las prácticas recomendadas: ¡cualquier idea sería muy apreciada!

Gracias

marca
fuente

Respuestas:

13

Una solución que he usado en el pasado (y he recomendado aquí y en StackOverflow antes) es crear dos esquemas adicionales:

CREATE SCHEMA shadow AUTHORIZATION dbo;
CREATE SCHEMA cache  AUTHORIZATION dbo;

Ahora cree una imitación de su tabla en el cacheesquema:

CREATE TABLE cache.IPLookup(...columns...);

Ahora cuando está haciendo su operación de cambio:

TRUNCATE TABLE cache.IPLookup;
BULK INSERT cache.IPLookup FROM ...;

-- the nice thing about the above is that it doesn't really
-- matter if it takes one minute or ten - you're not messing
-- with a table that anyone is using, so you aren't going to
-- interfere with active users.


-- this is a metadata operation so extremely fast - it will wait
-- for existing locks to be released, but won't block new locks
-- for very long at all:

BEGIN TRANSACTION;
  ALTER SCHEMA shadow TRANSFER    dbo.IPLookup;
  ALTER SCHEMA dbo    TRANSFER  cache.IPLookup;
COMMIT TRANSACTION;


-- now let's move the shadow table back over to
-- the cache schema so it's ready for next load:

ALTER SCHEMA cache TRANSFER shadow.IPLookup;
TRUNCATE TABLE cache.IPLookup; 

-- truncate is optional - I usually keep the data
-- around for debugging, but that's probably not
-- necessary in this case.

Esto será más engorroso si tiene claves externas y otras dependencias (ya que es posible que deba eliminarlas y volver a crearlas) y, por supuesto, invalida completamente las estadísticas, etc. y esto, a su vez, puede afectar los planes, pero si el Lo más importante es obtener datos precisos frente a sus usuarios con una interrupción mínima, esto puede ser un enfoque a tener en cuenta.

Aaron Bertrand
fuente
Gracias, otra alternativa interesante: creo que las dos últimas declaraciones no son del todo correctas, deberían mover la sombra al caché y truncar el caché. Me pregunto si los sinónimos también podrían usarse.
Mark
Tienes razón, los mezclé. No estoy seguro exactamente de cómo los sinónimos serían mejores, supongo que también es un enfoque: tenga una vista que apunte a un sinónimo y cambie el sinónimo subyacente en una transacción cuando haya completado la otra versión. Personalmente, esto me parece un poco mejor: cuando consulta dbo.IPLookup, sabe que esa es la tabla "actual" sin tener que perseguir la vista y el sinónimo.
Aaron Bertrand
Para su información, escribí sobre esto con más detalle esta semana: sqlperformance.com/2012/08/t-sql-queries/…
Aaron Bertrand