Estamos desarrollando una búsqueda como parte de un sistema más grande.
Tenemos Microsoft SQL Server 2014 - 12.0.2000.8 (X64) Standard Edition (64-bit)
con esta configuración:
CREATE TABLE NewCompanies(
[Id] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](400) NOT NULL,
[Phone] [nvarchar](max) NULL,
[Email] [nvarchar](max) NULL,
[Contacts1] [nvarchar](max) NULL,
[Contacts2] [nvarchar](max) NULL,
[Contacts3] [nvarchar](max) NULL,
[Contacts4] [nvarchar](max) NULL,
[Address] [nvarchar](max) NULL,
CONSTRAINT PK_Id PRIMARY KEY (Id)
);
Phone
es una cadena de dígitos estructurados separados por comas como"77777777777, 88888888888"
Email
es una cadena de correos electrónicos estructurados con comas similares"email1@gmail.com, email2@gmail.com"
(o sin comas"email1@gmail.com"
)Contacts1, Contacts2, Contacts3, Contacts4
son campos de texto donde los usuarios pueden especificar detalles de contacto en forma libre. Me gusta"John Smith +1 202 555 0156"
o"Bob, +1-999-888-0156, bob@company.com"
. Estos campos pueden contener correos electrónicos y teléfonos que queremos buscar más.
Aquí creamos texto completo
-- FULL TEXT SEARCH
CREATE FULLTEXT CATALOG NewCompanySearch AS DEFAULT;
CREATE FULLTEXT INDEX ON NewCompanies(Name, Phone, Email, Contacts1, Contacts2, Contacts3, Contacts4, Address)
KEY INDEX PK_Id
Aquí hay una muestra de datos
INSERT INTO NewCompanies(Id, Name, Phone, Email, Contacts1, Contacts2, Contacts3, Contacts4)
VALUES ('7BA05F18-1337-4AFB-80D9-00001A777E4F', 'PJSC Azimuth', '79001002030, 78005005044', 'regular@hotmail.com, s.m.s@gmail.com', 'John Smith', 'Call only at weekends +7-999-666-22-11', NULL, NULL)
En realidad, tenemos alrededor de 100 mil de esos registros.
Esperamos que los usuarios puedan especificar una parte del correo electrónico como "@ gmail.com" y esto debería devolver todas las filas con direcciones de correo electrónico de Gmail en cualquiera de los Email, Contacts1, Contacts2, Contacts3, Contacts4
campos.
Lo mismo para los números de teléfono. Los usuarios pueden buscar un patrón como "70283" y una consulta debe devolver los teléfonos con estos dígitos en ellos. Incluso es para Contacts1, Contacts2, Contacts3, Contacts4
campos de formulario libre donde probablemente deberíamos eliminar todos menos los dígitos y los caracteres de espacio antes de buscar.
Solíamos usar LIKE
para la búsqueda cuando teníamos alrededor de 1500 registros y funcionó bien, pero ahora tenemos muchos registros y la LIKE
búsqueda lleva infinitos para obtener resultados.
Así es como intentamos obtener datos desde allí:
SELECT * FROM NewCompanies WHERE CONTAINS((Email, Contacts1, Contacts2, Contacts3, Contacts4), '"s.m.s@gmail.com*"') -- this doesn't get the row
SELECT * FROM NewCompanies WHERE CONTAINS((Phone, Contacts1, Contacts2, Contacts3, Contacts4), '"6662211*"') -- doesn't get anything
SELECT * FROM NewCompanies WHERE CONTAINS(Name, '"zimuth*"') -- doesn't get anything
@gmail.com
como término de búsqueda porque el @
carácter es un separador de palabras. En otras palabras, según la versión de SQL Server que tiene, palabras en el índice para user@gmail.com
serán o bien (A) user
, gmail
y com
o (B) user
, user@gmail.com
, gmail
y com
. REF: Cambios de comportamiento en la búsqueda de texto completo
.
.
SELECT * FROM NewCompanies WHERE Id IN (SELECT ID from .... where MyOuterApply.EmailCol1 LIKE '%'+@SearchString+'%') OR Id IN (SELECT ID from .... where MyOuterApply.EmailCol2 LIKE '%'+@SearchString+'%')
Cree alrededor de cinco índices individuales en cada uno de los campos e incluya la clave principal.
nvarchar(MAX)
aquí? Nunca he oído hablar, ni he conocido a nadie cuyo nombre tenga 1 mil millones de caracteres de largo. Y, según esta respuesta , una dirección de correo electrónico no puede tener más de 254 caracteres; así que también tienes 1 billón de personajes desperdiciados allí.