Pregunta

Tenemos una consulta para eliminar algunas filas de la tabla en función de un campo de ID (clave primaria). Es una consulta bastante sencillo:

delete all from OUR_TABLE where ID in (123, 345, ...)

El problema es no.of los identificadores pueden ser enormes (Ej. 70k), por lo que la consulta tarda mucho tiempo. ¿Hay alguna manera de optimizar esto? (Estamos utilizando Sybase - si lo que importa).

¿Fue útil?

Solución

Considere la ejecución de este en lotes. Un bucle se ejecuta 1000 registros a la vez puede ser mucho más rápido que una consulta que hace todo y, además, no se mantendrá la tabla bloqueada para otros usuarios durante el tiempo de un tirón.

Si tienes eliminación en cascada (y un montón de tablas de claves foráneas afectadas) o desencadena involucrados, es posible que tenga que ejecutar en lotes más pequeños. Vas a tener que experiement para ver cuál es el mejor número para su situación. He tenido mesas en las que he tenido que eliminar en lotes de 100 y otros en los que trabajaban 50.000 (afortunado en ese caso, ya que estaba Eliminación de un millón de discos).

Pero en todo, incluso me gustaría poner mis valores clave que tengo la intención de eliminar en una tabla temporal y eliminar de allí.

Otros consejos

Hay dos maneras de hacer declaraciones como ésta realizan:

  1. Crea una nueva tabla y copiar todos, pero los registros a borrar. Intercambiar las tablas después (alter table name ...) Sugiero a darle una oportunidad, incluso cuando suena estúpido. Algunas bases de datos son mucho más rápidos en la copia que al borrar.

  2. Partición las tablas. Crear tablas N y utilizar a fin de unirse a ellos en una sola. Ordenar las filas en diferentes tablas agrupados por el criterio de eliminación. La idea es eliminar una tabla entera en lugar de eliminar filas individuales.

Me pregunto si al analizar una cláusula IN con 70K artículos en que es un problema. ¿Ha tratado de una tabla temporal con una unirse a su lugar?

Puede Sybase argumentos mango 70K en cláusula IN? Todas las bases de datos con los que trabajé tienen algún límite en el número de argumentos a favor de la cláusula IN. Por ejemplo, Oracle tiene límite de alrededor de 1.000.

Se puede crear en lugar de subselección cláusula IN? Que acortará sql. Tal vez eso podría ayudar a un gran número de tales valores en la cláusula IN. Algo como esto:

  DELETE FROM OUR_TABLE WHERE ID IN 
        (SELECT ID FROM somewhere WHERE some_condition)

La eliminación de gran número de registros se puede acelerar con algunas intervenciones en la base de datos, si lo permite el modelo de base de datos. He aquí algunas estrategias:

  1. puede acelerar las cosas al dejar caer los índices, la eliminación de registros y volver a crear los índices de nuevo. Esto eliminará los árboles de índices de reequilibrio, mientras que la eliminación de registros.

    • Borrar todos los índices en la tabla
    • Eliminar registros
    • recrear índices
    • Si usted tiene un montón de relaciones con esta tabla, pruebe a desactivar las restricciones si está absolutamente seguro de que el comando de eliminar no romperá ninguna restricción de integridad. Eliminar irá mucho más rápido porque la base de datos no va a controlar la integridad. Habilitar las restricciones después de eliminar.
    • desactivar las restricciones de integridad, desactivar las restricciones de comprobación
    • Eliminar registros
    • Activar restricciones
    • desencadenantes desactivar en la mesa, si tiene alguno, y si las reglas de negocio que permiten. Eliminar registros, a continuación, permiten a los factores desencadenantes.

    • última, hacer como otros sugerido - hacer una copia de la tabla que contiene filas que no se van a eliminar, a continuación, colocar original, cambiar el nombre de la copia y volver a crear restricciones de integridad, si los hay.

Me gustaría tratar combinación de 1, 2 y 3. Si esto no funciona, entonces 4. Si todo es lento, me gustaría ver a mayor caja -. Más memoria, discos más rápidos

Para saber lo que está consumiendo el rendimiento!

En muchos casos es posible utilizar una de las soluciones aportadas. Pero puede haber otros (basado en el conocimiento de Oracle, así que las cosas serán diferentes en otras bases de datos de edición:. Acaba de ver que usted ha mencionado Sybase):

  • ¿Tiene claves externas en esa mesa? Asegura que los identificadores de referencia se indexan
  • ¿Tiene índices en esa mesa? Puede ser que droping antes de eliminar y volver a crear después de la eliminación puede ser más rápido.
  • Comprobar el plan de ejecución. ¿Está utilizando un índice donde un escaneo completo de tabla puede ser más rápido? ¿O de otra forma? CONSEJOS podrían ayudar
  • en lugar de un selecto en new_table como se sugirió anteriormente crear una mesa de selección como podría ser aún más rápido.

Pero recuerda:. Averiguar qué se usa el desempeño del primer

Cuando se está utilizando sentencias DDL que asegúrese de entender y aceptar las consecuencias que podría tener en las transacciones y las copias de seguridad.

Trate de clasificar el ID que está de paso en "in" en el mismo orden en la mesa, o el índice se almacena en. A continuación, puede conseguir más accesos a la caché de disco.

Poner el ID que desea eliminar en una tabla temporal que ha ordenado la ID en el mismo orden que la mesa principal, puede dejar que la base de datos hacer una simple escaneado sobre la mesa principal.

Se podría tratar de usar más de una conexión y escupiendo el trabajo sobre las conexiones con el fin de utilizar todas las CPU en el servidor de base de datos, sin embargo, pensar en lo cerraduras serán sacados etc primero.

También creo que la tabla temporal es probable que la mejor solución.

Si se va a hacer un "eliminar de .. donde ID en (seleccione Identificación de ...)" todavía puede ser lento, con consultas de gran tamaño, sin embargo. por lo tanto sugiero que elimine el uso de un unan -. mucha gente no sabe acerca de que la funcionalidad

Por lo tanto, dada esta tabla de ejemplo:

    -- set up tables for this example
    if exists (select id from sysobjects where name = 'OurTable' and type = 'U')
        drop table OurTable
    go

    create table OurTable (ID integer primary key not null)
    go
    insert into OurTable (ID) values (1)
    insert into OurTable (ID) values (2)
    insert into OurTable (ID) values (3)
    insert into OurTable (ID) values (4)
    go

A continuación, podemos escribir nuestro código de borrado de la siguiente manera:

    create table #IDsToDelete (ID integer not null)
    go
    insert into #IDsToDelete (ID) values (2)
    insert into #IDsToDelete (ID) values (3)
    go
    -- ... etc ...
    -- Now do the delete - notice that we aren't using 'from'
    -- in the usual place for this delete
    delete OurTable from #IDsToDelete
       where OurTable.ID = #IDsToDelete.ID
    go
    drop table #IDsToDelete
    go
    -- This returns only items 1 and 4
    select * from OurTable order by ID
    go

¿Tiene our_table tener una referencia de supresión en cascada?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top