mysql búsqueda de texto completo en chino desde la entrada hasta el abandono

Al igual que la consulta difusa de coincidencia completa no puede usar el índice, siempre es un problema espinoso de la consulta SQL, entonces, ¿la búsqueda de texto completo de MySQL realmente puede resolver este problema?

antecedentes

Recientemente, encontré un problema de optimización de consultas en mi trabajo. El SQL simplificado es el siguiente:

SELECT
	* 
FROM
	wxswj_nsrxx 
WHERE
	nsrmc LIKE '%东鹏%' 
	OR nsrsbh LIKE '%东鹏%' 
	OR shxydm LIKE '%东鹏%';

Preguntas:
1. Se utiliza una consulta aproximada de coincidencia completa
2. Se utiliza una palabra clave O

Obviamente, dicha consulta no se puede indexar y, debido a que el volumen de datos de la tabla es muy grande, con más de 5 millones de datos, la velocidad de respuesta de toda la consulta es muy insatisfactoria.

Búsqueda de texto completo en chino en la práctica

Instrucciones para la inserción de segmentación de ngram:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-search-ngram.html agregar descripción del enlace

1. Idea de optimización:
la consulta de coincidencia aproximada china implica principalmente la segmentación de palabras y la recuperación de texto completo, y hay un tipo de índice en mysql que es el índice de texto completo FULLTEXT . Así que quiero resolver el problema de la consulta difusa de coincidencia completa en mysql mediante la indexación de texto completo.

2. Descripción:
Antes de MySQL 5.7.6, la indexación de texto completo solo admite la indexación de texto completo en inglés, pero no la indexación de texto completo en chino. Necesita usar un segmentador de palabras para preprocesar párrafos chinos en palabras y luego almacenarlos en la base de datos.
A partir de MySQL 5.7.6, MySQL tiene un analizador de texto completo ngram incorporado para admitir la segmentación de palabras chinas.

3. Ver la versión actual de la base de datos:

select version() from dual;

El resultado es 5.7.28, que admite la búsqueda de texto completo en chino

4. Restricciones
en la búsqueda de texto completo: Los índices FULLTEXT se crean en columnas basadas en texto (columnas CHAR, VARCHAR o TEXT).
Los índices de texto completo solo se pueden crear en columnas CHAR, VARCHAR o TEXT.
Cada tabla solo puede tener un índice de búsqueda de texto completo
. El índice de búsqueda de texto completo compuesto por varias columnas debe usar el mismo conjunto de caracteres y clasificación.

5.
Antes de cerrar la optimización de sql de la caché de consultas, la caché de consultas generalmente se cierra:
MOSTRAR VARIABLES COMO'query_cache% ';
establecer global query_cache_size = 0;
establecer global query_cache_type = 0;

MOSTRAR VARIABLES COMO 'query_cache%';

6. Cree un índice de texto completo

ALTER TABLE `wxswj`.`wxswj_nsrxx`  ADD FULLTEXT INDEX `ft_index`(`nsrmc`,`nsrsbh`,`shxydm`) WITH PARSER ngram;

7. Usar índice de texto completo Use el índice de texto completo
mediante la declaración ** MATCH (col1, col2, ...) AGAINST (expr [search_modifier]) **.

SELECT
	* 
FROM
	wxswj_nsrxx MATCH ( `nsrmc`, `nsrsbh`, `shxydm` ) against ( '东鹏' IN boolean MODE )

Los tres campos de 东鹏coincidencia difusa ,, se utilizan aquí nsrmc, nsrsbhy se devuelve el registro correspondiente si shxydmalguno de los campos contiene la clave de consulta 东鹏.

8. El plan de ejecución de consultas
Inserte la descripción de la imagen aquí
utiliza una nueva búsqueda combinada de texto completo y la referencia alcanza el nivel constante.

9. Efecto de optimización El
rendimiento de la consulta se ha mejorado más de 100 veces.

pozo

Hasta ahora todo parece ir muy bien, pero pronto apareció el hoyo.
Cuando la palabra clave de la consulta es demasiado larga, ¿se produce una excepción?

Pregunta 1: la consulta FTS excede el límite de caché de resultados
cuando se utiliza una condición de consulta relativamente larga para hacer coincidir la consulta o incluso ejecutar el plan de consulta, se produce una excepción:

188 - FTS query exceeds result cache limit

Explicación de la excepción en el sitio web oficial de mysql:
https://bugs.mysql.com/bug.php?id=86036

Cada consulta de búsqueda de texto completo o búsqueda de texto completo InnoDB de cada hilo tiene un límite de caché en los resultados de la consulta, que se define en bytes. Los resultados de la consulta de búsqueda de texto completo de InnoDB intermedio y final se procesan en la memoria. Puede usar innodb_ft_result_cache_limit para establecer el límite de tamaño. El almacenamiento en caché de resultados de consultas de búsqueda de texto completo puede evitar un consumo excesivo de memoria cuando los resultados de la consulta de búsqueda de texto completo de InnoDB son muy grandes (por ejemplo, millones o cientos de millones de filas). Si se alcanza el límite de tamaño de la caché de resultados, se devuelve un error que indica que la consulta excede la memoria máxima permitida.

Soluciones recomendadas:
Inserte la descripción de la imagen aquí
1. Aumente el valor de innodb_ft_result_cache_limit para que sea mayor que 4G

SHOW VARIABLES LIKE 'innodb_ft_result_cache_limit%';
set global innodb_ft_result_cache_limit=4000000000;

2. Optimice la declaración de la consulta, limite el número de registros devueltos por la consulta y reduzca la enorme caché de los resultados intermedios. Generalmente está limitado mostrando el límite especificado.

Problema 2: La velocidad de consulta es muy inestable,
modificando el valor de innodb_ft_result_cache_limit, solucionamos el problema anormal del límite de caché.
En ese momento, cuando intentamos modificar las condiciones de la consulta, encontramos que el rendimiento de la consulta era muy inestable.
A veces, la velocidad de consulta es muy rápida y, a veces, ni siquiera es tan buena como la consulta del módulo de coincidencia completa similar.
Especialmente cuando la condición de la consulta es muy larga, el problema es muy obvio y el rendimiento de la consulta no está garantizado en absoluto.

SELECT
	* 
FROM
	wxswj_nsrxx MATCH ( `nsrmc`, `nsrsbh`, `shxydm` ) against ( '中国航天工业科学技术咨询有限公司' IN boolean MODE )

rendirse

Después de investigar varios materiales, no encontré una mejor solución y finalmente decidí renunciar a regañadientes.

Declaración de prueba

create table test(
id int(11) not null primary key auto_increment,
name varchar(100) not null comment '工商名',
brand varchar(100) default null comment '品牌名',
en varchar(100) default null comment '英文名',
fulltext key (name,brand,en) with parser ngram
)engine=innodb default charset=utf8;
insert into test (name,brand,en) values ('芜湖美的厨卫电气制造有限公司','aa','wh');
insert into test (name,brand,en) values ('北京凡客尚品电子商务有限公司','aa','ef');
insert into test (name,brand,en) values ('凡客诚品(北京)科技有限公司','aa','dfd');
insert into test (name,brand,en) values ('瞬联讯通科技(北京)有限公司','aa','sdfs');
insert into test (name,brand,en) values ('北京畅捷通讯有限公司','aa','wsdh');
insert into test (name,brand,en) values ('北京畅捷通支付技术有限公司','aa','df');
insert into test (name,brand,en) values ('畅捷通信息技术股份有限公司','aa','whdfgh');
insert into test (name,brand,en) values ('北京畅捷科技有限公司','aa','dgdf');
insert into test (name,brand,en) values ('中国航天工业科学技术咨询有限公司','aa','whffgh');
insert into test (name,brand,en) values ('北京·松下彩色显象管有限公司','aa','wfghfgh');
insert into test(name,brand,en) select name,brand,en from test;
insert into test(name,brand,en) select name,brand,en from test;
insert into test(name,brand,en) select name,brand,en from test;
insert into test(name,brand,en) select name,brand,en from test;
insert into test(name,brand,en) select name,brand,en from test;
insert into test(name,brand,en) select name,brand,en from test;

EXPLAIN  SELECT  *  from  test  where  match  (name,brand,en)  against  ('通讯录' IN BOOLEAN MODE) LIMIT 100;

La cantidad total de datos de prueba creados es: 655360
seleccionar recuento (*) de la prueba;

SELECT  *  from  test  where name like '%美的%' or brand like '%美的%' or en like '%美的%';
耗时:0.544

EXPLAIN  SELECT  *  from  test  where  match  (name,brand,en)  against  ('美的' IN BOOLEAN MODE) LIMIT 100;
耗时:0.150



SELECT  *  from  test  where name like '%芜湖美的厨卫电气制造有限公司%' or brand like '%芜湖美的厨卫电气制造有限公司%' or en like '%芜湖美的厨卫电气制造有限公司%';
耗时:0.679

EXPLAIN  SELECT  *  from  test  where  match  (name,brand,en)  against  ('芜湖美的厨卫电气制造有限公司' IN BOOLEAN MODE) LIMIT 100;
耗时:5.626

Al agregar comillas dobles, se realiza la búsqueda de frase exacta y las condiciones de búsqueda no coinciden con la segmentación de palabras. Probemos:
Inserte la descripción de la imagen aquí

 SELECT  *  from  test  where  match  (name,brand,en)  against  ('"芜湖美的厨卫电气制造有限公司"' IN BOOLEAN MODE) LIMIT 100;
耗时:5.626

No se encontró ningún impacto en el rendimiento de las consultas.

A través de experimentos, se encontró que cuanto más larga es la condición de la consulta, más lento es el rendimiento de la consulta.
Puede probarlo y sentirlo usted mismo.

Le invitamos a compartir cualquier sugerencia sobre el uso de la búsqueda de texto completo de mysql.

En conclusión

Este experimento demuestra que MySQL tiene un soporte limitado para la búsqueda de texto completo, la restricción es relativamente grande y el rendimiento de la consulta no está garantizado. En muchos casos, puede que no sea tan bueno como usar una consulta similar directamente.
Considere jugar una mesa pequeña con cientos de miles de datos.
Cuando se requiere una consulta difusa de coincidencia completa para algunas tablas grandes, en primer lugar, discuta con el lado empresarial si solo puede admitir la consulta difusa previa a la coincidencia y, en segundo lugar, aumente otras condiciones de consulta tanto como sea posible y limite el número de registros coincidentes hasta el límite.
En consultas complejas, y deben requerir compatibilidad con consultas difusas de coincidencia completa y requisitos estrictos sobre el rendimiento de las consultas, se recomienda Elasticsearch.

Sígueme en el chat privado y recibe tutoriales en video gratis.
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Más emocionante, sígueme.
Leyenda: sigue al anciano para aprender java

Supongo que te gusta

Origin blog.csdn.net/w1014074794/article/details/106746114
Recomendado
Clasificación