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
- 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');
- 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');
- aumentar la clave principal
ALTER TABLE TEST_LOG_DETAIL
ADD CONSTRAINT TEST_LOG_DETAIL_PK PRIMARY KEY (ID)
ENABLE;
- 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;
- 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;
- 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
- Actualizar 3000 piezas de datos
UPDATE TEST_LOG_DETAIL SET MONEY = 1001 WHERE USERNAME ='TESTADMIN'
- Eliminar 3000 piezas de datos
DELETE TEST_LOG_DETAIL WHERE USERNAME ='TESTADMIN'
- 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
- 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);
- 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.
-
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.
-
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
-
El consumo de tiempo de eliminar y ejecutar el índice se reduce considerablemente, y el tiempo de no ejecutar el índice se reduce ligeramente
- eliminar índice de nombre de usuario
DROP index idx_TEST_USERNAME;
- Agregue un índice al campo insert_time
create index idx_TEST_INSERT_TIME ON TEST_LOG_DETAIL(INSERT_TIME);
- 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
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
-
El consumo de tiempo de consulta e indexación se reduce considerablemente.
-
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
-
El tiempo que lleva eliminar y recorrer el índice se reduce considerablemente, y el tiempo que lleva no recorrer el índice aumenta
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.