sql >> Base de Datos >  >> RDS >> Mysql

MySQL:índice compuesto de texto completo + btree?

Usar IN BOOLEAN MODE .

El índice de fechas no es útil. No hay forma de combinar los dos índices.

Tenga cuidado, si un usuario busca algo que aparece en 30 000 filas, la consulta será lenta. No hay forma de evitarlo.

Sospecho que tienes un TEXT columna de la tabla? Si es así, hay esperanza. En lugar de hacer ciegamente SELECT * , busquemos primero los ID y obtengamos el LIMIT aplicado, luego hacer el * .

SELECT a.* 
    FROM tbl AS a
    JOIN ( SELECT date, id
             FROM tbl
             WHERE MATCH(...) AGAINST (...)
             ORDER BY date DESC
             LIMIT 10 ) AS x
        USING(date, id)
    ORDER BY date DESC;

Junto con

PRIMARY KEY(date, id),
INDEX(id),
FULLTEXT(...)

Esta formulación e indexación debería funcionar así:

  1. Usar FULLTEXT para encontrar filas de 30K, entregue el PK.
  2. Con PK, ordene 30 000 filas por date .
  3. Elija los últimos 10, entregando date, id
  4. Regresa a la mesa 10 veces usando el PK.
  5. Ordenar de nuevo. (Sí, esto es necesario).

Más (Respondiendo a una plétora de Comentarios):

El objetivo detrás de mi reformulación es evitar obtener todos columnas de 30K filas En su lugar, solo obtiene la PRIMARY KEY , luego lo reduce a 10, luego obtiene * solo 10 filas. Mucho menos cosas amontonadas.

Acerca de COUNT en una tabla InnoDB:

  • INDEX(col) hace que un index el escaneo funciona para SELECT COUNT(*) o SELECT COUNT(col) sin un WHERE .
  • Sin INDEX(col), SELECT COUNT(*)will use the "smallest" index; but SELECT COUNT(col)` necesitará una tabla escanear.
  • Un escaneo de tabla es generalmente más lento que un escaneo de índice.
  • Tenga cuidado con el tiempo:se ve afectado significativamente por si el índice y/o la tabla ya están en caché en la RAM.

Otra cosa sobre FULLTEXT es el + delante de las palabras, para decir que cada palabra debe existir, de lo contrario no hay coincidencia. Esto puede reducir los 30K.

El FULLTEXT index entregará la date, id es orden aleatorio, no orden PK. De todos modos, es 'incorrecto' asumir cualquier orden, por lo tanto, es 'correcto' agregar ORDER BY , luego deje que el Optimizador lo tire si sabe que es redundante. Y, a veces, el Optimizer puede aprovechar el ORDER BY (no en tu caso).

Eliminando solo el ORDER BY , en muchos casos, hace que una consulta se ejecute mucho más rápido. Esto se debe a que evita obtener, digamos, 30 000 filas y clasificarlas. En su lugar, simplemente entrega "cualquier" 10 filas.

(No tengo experiencia con Postgres, por lo que no puedo abordar esa pregunta).