La consulta de grandes tablas de registro de Oracle es lenta y los petabytes de datos se generan localmente de manera aleatoria para probar el impacto de agregar índices en diferentes campos en las operaciones DML.

1. Antecedentes

Dado que hay una tabla de registro de mil millones de niveles de Oracle en línea, la consulta es lenta sin indexación, así que cree una tabla de mil millones de niveles y una tabla de decenas de millones de niveles localmente para las pruebas de indexación. Observe el tiempo de consulta antes y después de agregar índices, y las operaciones de inserción, actualización y eliminación de DML consumen horas

dos, operación

  1. Cree una tabla de datos de mil millones de niveles y una tabla de datos de decenas de millones de niveles, y establezca id como clave principal
  • Decenas de millones de creación de mesas
CREATE TABLE TEST_LOG_DETAIL AS
SELECT
	ROWNUM AS ID,
	SYSDATE + ROWNUM / 24 / 3600 AS INSERT_TIME,
	TRUNC(DBMS_RANDOM.VALUE(0, 100)) AS MONEY,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS USERFROM,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PRODUCT,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS TAG,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PAY_CODE,
	DBMS_RANDOM.STRING('x',
	8) USERNAME,
	DBMS_RANDOM.STRING('x',
	16) ORDER_ID,
	DBMS_RANDOM.STRING('x',
	8) ADD_FROM
FROM xmltable('1 to 15000000');

inserte la descripción de la imagen aquí

  • creación de mesa mil millones
CREATE TABLE TEST1_LOG_DETAIL AS
SELECT
	ROWNUM AS ID,
	SYSDATE + ROWNUM / 24 / 3600 AS INSERT_TIME,
	TRUNC(DBMS_RANDOM.VALUE(0, 100)) AS MONEY,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS USERFROM,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PRODUCT,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS TAG,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PAY_CODE,
	DBMS_RANDOM.STRING('x',
	8) USERNAME,
	DBMS_RANDOM.STRING('x',
	16) ORDER_ID,
	DBMS_RANDOM.STRING('x',
	8) ADD_FROM
FROM xmltable('1 to 150000000');

inserte la descripción de la imagen aquí

  • aumentar la clave principal
ALTER TABLE TEST_LOG_DETAIL
ADD CONSTRAINT TEST_LOG_DETAIL_PK PRIMARY KEY (ID)
ENABLE;

inserte la descripción de la imagen aquí

  1. Trabajo preparatorio antes de probar DML, establecer el incremento automático de la clave principal, evitar la falla de inserción de la clave principal de identificación
  • Aumente la función de incremento automático de clave principal (establezca el número de incremento automático para iniciar el incremento automático desde el final de la identificación)
CREATE SEQUENCE TEST_ID_SEQ
INCREMENT BY 1
START WITH 15000001
MAXVALUE 999999999
NOCYCLE
NOCACHE;

inserte la descripción de la imagen aquí

  • Cree un disparador de incremento automático de clave principal (modificado de acuerdo con diferentes tablas)
CREATE OR REPLACE TRIGGER TEST_ID_SEQ_TRG
BEFORE INSERT ON "TEST_LOG_DETAIL"
FOR EACH ROW
WHEN (NEW."ID" IS NULL)
BEGIN
  SELECT TEST_ID_SEQ.NEXTVAL
  INTO :NEW."ID"
  FROM DUAL;
END;

inserte la descripción de la imagen aquí

  1. Insertar 3000 datos aleatorios
INSERT
	INTO
	TEST_LOG_DETAIL (id,
	INSERT_TIME,
	MONEY,
	USERFROM,
	PRODUCT,
	TAG,
	PAY_CODE,
	USERNAME,
	ORDER_ID,
	ADD_FROM)
SELECT
	NULL,
	SYSDATE + ROWNUM / 24 / 3600 AS INSERT_TIME,
	TRUNC(DBMS_RANDOM.VALUE(0, 100)) AS MONEY,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS USERFROM,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PRODUCT,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS TAG,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PAY_CODE,
	'TESTADMIN' USERNAME,
	DBMS_RANDOM.STRING('x',
	16) ORDER_ID,
	DBMS_RANDOM.STRING('x',
	8) ADD_FROM
FROM
	DUAL
CONNECT BY
	LEVEL <= 3000

inserte la descripción de la imagen aquí

  1. Actualizar 3000 piezas de datos
UPDATE TEST_LOG_DETAIL SET MONEY  = 1001 WHERE USERNAME ='TESTADMIN'

inserte la descripción de la imagen aquí

  1. Eliminar 3000 piezas de datos
DELETE  TEST_LOG_DETAIL  WHERE  USERNAME ='TESTADMIN'

inserte la descripción de la imagen aquí

  1. Operación de consulta DQL
SELECT
	USERNAME,
	MONEY,
	TO_CHAR(insert_time, 'yyyy-MM-dd HH24:mi:ss') AS insert_time,
	ADD_FROM
FROM
	TEST_LOG_DETAIL
WHERE
	USERNAME = 'QUWO12TO'
	AND userfrom = 0
	AND insert_time >= TO_DATE('2022-12-21', 'YYYY-MM-DD')
	AND insert_time <= TO_DATE('2023-01-03', 'YYYY-MM-DD')+ 1
ORDER BY
	insert_time DESC

inserte la descripción de la imagen aquí

  1. El campo de nombre de usuario crea un índice y las operaciones DML no se pueden realizar durante la creación
create index idx_TEST_USERNAME on TEST_LOG_DETAIL(USERNAME);

inserte la descripción de la imagen aquí

  1. Vuelva a probar la operación DQL DML anterior para ver el tiempo
  • El consumo de tiempo de consulta e indexación se reduce considerablemente.
    inserte la descripción de la imagen aquí

  • Lleva mucho tiempo insertar el contenido del nombre de usuario del campo de índice cuando está arreglado, y lleva mucho tiempo insertarlo cuando no está arreglado.
    inserte la descripción de la imagen aquí
    inserte la descripción de la imagen aquí

  • El consumo de tiempo de actualización y ejecución del índice se reduce considerablemente, y el tiempo de no ejecución del índice se reduce ligeramenteinserte la descripción de la imagen aquíinserte la descripción de la imagen aquí

  • El consumo de tiempo de eliminar y ejecutar el índice se reduce considerablemente, y el tiempo de no ejecutar el índice se reduce ligeramente
    inserte la descripción de la imagen aquí
    inserte la descripción de la imagen aquí

  1. eliminar índice de nombre de usuario
DROP index idx_TEST_USERNAME;

inserte la descripción de la imagen aquí

  1. Agregue un índice al campo insert_time
create index idx_TEST_INSERT_TIME ON TEST_LOG_DETAIL(INSERT_TIME);

inserte la descripción de la imagen aquí

  1. Vuelva a probar la operación DQL DML anterior para ver el tiempo
  • Inserte 3000 piezas de datos, el cambio de tiempo de inserción y el consumo de tiempo fijo se reducen considerablemente
    inserte la descripción de la imagen aquí
INSERT
	INTO
	TEST_LOG_DETAIL (id,
	INSERT_TIME,
	MONEY,
	USERFROM,
	PRODUCT,
	TAG,
	PAY_CODE,
	USERNAME,
	ORDER_ID,
	ADD_FROM)
SELECT
	NULL,
	TO_DATE('2023-01-03 16:20:00','yyyy-mm-dd hh24:mi:ss')  AS INSERT_TIME,
	TRUNC(DBMS_RANDOM.VALUE(0, 100)) AS MONEY,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS USERFROM,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PRODUCT,
	TRUNC(1004) AS TAG,
	TRUNC(DBMS_RANDOM.VALUE(0, 9)) AS PAY_CODE,
	DBMS_RANDOM.STRING('x',
	8) USERNAME,
	DBMS_RANDOM.STRING('x',
	16) ORDER_ID,
	DBMS_RANDOM.STRING('x',
	8) ADD_FROM
FROM
	DUAL
CONNECT BY
	LEVEL <= 3000

inserte la descripción de la imagen aquí

  • El consumo de tiempo de consulta e indexación se reduce considerablemente.

    inserte la descripción de la imagen aquí

  • El consumo de tiempo de actualización y ejecución del índice se reduce considerablemente, y el tiempo de no ejecución del índice se reduce ligeramente

    inserte la descripción de la imagen aquí

    inserte la descripción de la imagen aquí

  • El tiempo que lleva eliminar y recorrer el índice se reduce considerablemente, y el tiempo que lleva no recorrer el índice aumenta
    inserte la descripción de la imagen aquí
    inserte la descripción de la imagen aquí

3. Conclusión

datos de la base de datos sin índice índice de nombre de usuario índice insert_time
Preguntar 9.458s 110ms 77ms
Insertar 3000 elementos 523ms 479ms 402ms
Actualizar 3000 elementos 9.548s 12ms 5ms
Eliminar 3000 elementos 9.542s 35ms 75ms

Después de agregar el índice, si la declaración SQL usa el índice, el tiempo que consumen las operaciones DQL y DML se reducirá considerablemente. Si no se usa el índice, el tiempo que consumen las operaciones DML puede aumentar. Personalmente, creo que si el la operación de consulta en la tabla de registro grande es frecuente y lenta, es insoportable Si es así, puede agregar índices a los campos de uso común, pero no agregue demasiados índices. La mayoría de los escenarios están optimizados para el rango de tiempo. Es mejor cargar el índice en el campo de tiempo Al mismo tiempo, debe tenerse en cuenta que la tabla no puede realizar operaciones DML al crear índices.

Supongo que te gusta

Origin blog.csdn.net/weixin_43288999/article/details/128529891
Recomendado
Clasificación