values two mysql group-by min

mysql min between two values



MySQL MIN GROUP BY en tablas grandes(> 8000 filas) (1)

Tengo la siguiente consulta:

SELECT contact_purl, contact_firstName, contact_lastName, MIN( contact_id ) AS MinID FROM contacts WHERE contact_client_id = 1 GROUP BY contact_purl HAVING COUNT( contact_id ) > 1

El objetivo es encontrar cualquier contacto con un duplicado "contact_purl" y devolver la primera entrada.

Me encuentro con un problema muy extraño ... Si la tabla tiene menos de 8,000 filas, la consulta se procesará en menos de 1 segundo. SIN EMBARGO, si la tabla tiene más de 8,000 filas, la consulta tomará consistentemente 338 segundos en promedio.

Aquí está el plan de consulta para la tabla con ~ 5000 filas:

Y para ~ 8000 filas:

La mesa...

CREATE TABLE IF NOT EXISTS `contacts` ( `contact_id` int(11) NOT NULL AUTO_INCREMENT, `contact_client_id` int(11) DEFAULT NULL, `contact_sales_id` int(11) DEFAULT NULL, `contact_campaign_id` int(11) DEFAULT NULL, `contact_purl` varchar(100) NOT NULL, `contact_purl1` varchar(50) DEFAULT NULL, `contact_purl2` varchar(50) DEFAULT NULL, `contact_firstName` varchar(50) NOT NULL, `contact_lastName` varchar(50) NOT NULL, `contact_organization` varchar(100) DEFAULT NULL, `contact_url_organization` varchar(200) DEFAULT NULL, `contact_position` varchar(50) DEFAULT NULL, `contact_email` varchar(100) DEFAULT NULL, `contact_phone` varchar(20) DEFAULT NULL, `contact_fax` varchar(20) NOT NULL, `contact_address1` varchar(100) DEFAULT NULL, `contact_address2` varchar(100) DEFAULT NULL, `contact_city` varchar(100) DEFAULT NULL, `contact_state` varchar(20) DEFAULT NULL, `contact_zip` varchar(10) DEFAULT NULL, `contact_IP` varchar(50) DEFAULT NULL, `contact_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `contact_pw` varchar(200) NOT NULL, `contact_subscribed` varchar(1) NOT NULL DEFAULT ''Y'', `contact_import` varchar(200) DEFAULT NULL, `contacts_c_1` varchar(500) DEFAULT NULL, `contacts_c_2` varchar(500) DEFAULT NULL, `contacts_c_3` varchar(500) DEFAULT NULL, `contacts_c_4` varchar(500) DEFAULT NULL, `contacts_c_5` varchar(500) DEFAULT NULL, `contacts_c_6` varchar(500) DEFAULT NULL, `contacts_c_7` varchar(500) DEFAULT NULL, `contacts_c_8` varchar(500) DEFAULT NULL, `contacts_c_9` varchar(500) DEFAULT NULL, `contacts_c_10` varchar(500) DEFAULT NULL, `contacts_c_11` varchar(500) DEFAULT NULL, `contacts_c_12` varchar(500) DEFAULT NULL, `contacts_c_13` varchar(500) DEFAULT NULL, `contacts_c_14` varchar(500) DEFAULT NULL, `contacts_c_15` varchar(500) DEFAULT NULL, `contacts_c_16` varchar(500) DEFAULT NULL, `contacts_c_17` varchar(500) DEFAULT NULL, `contacts_c_18` varchar(500) DEFAULT NULL, `contacts_c_19` varchar(500) DEFAULT NULL, `contacts_c_20` varchar(500) DEFAULT NULL, `contacts_c_21` varchar(500) DEFAULT NULL, `contacts_c_22` varchar(500) DEFAULT NULL, `contacts_c_23` varchar(500) DEFAULT NULL, `contacts_c_24` varchar(500) DEFAULT NULL, `contacts_c_25` varchar(500) DEFAULT NULL, `contacts_c_26` varchar(500) DEFAULT NULL, `contacts_c_27` varchar(500) DEFAULT NULL, `contacts_c_28` varchar(500) DEFAULT NULL, `contacts_c_29` varchar(500) DEFAULT NULL, `contacts_c_30` varchar(500) DEFAULT NULL, `contacts_c_31` varchar(500) DEFAULT NULL, `contacts_c_32` varchar(500) DEFAULT NULL, `contacts_c_33` varchar(500) DEFAULT NULL, `contacts_c_34` varchar(500) DEFAULT NULL, `contacts_c_35` varchar(500) DEFAULT NULL, `contacts_c_36` varchar(500) DEFAULT NULL, `contacts_c_37` varchar(500) DEFAULT NULL, `contacts_c_38` varchar(500) DEFAULT NULL, `contacts_c_39` varchar(500) DEFAULT NULL, `contacts_c_40` varchar(500) DEFAULT NULL, `contacts_c_41` varchar(500) DEFAULT NULL, `contacts_c_42` varchar(500) DEFAULT NULL, `contacts_c_43` varchar(500) DEFAULT NULL, `contacts_c_44` varchar(500) DEFAULT NULL, `contacts_c_45` varchar(500) DEFAULT NULL, `contacts_c_46` varchar(500) DEFAULT NULL, `contacts_c_47` varchar(500) DEFAULT NULL, `contacts_c_48` varchar(500) DEFAULT NULL, `contacts_c_49` varchar(500) DEFAULT NULL, `contacts_c_50` varchar(500) DEFAULT NULL, `contacts_i_1` varchar(100) DEFAULT NULL, `contacts_i_2` varchar(100) DEFAULT NULL, `contacts_i_3` varchar(100) DEFAULT NULL, `contacts_i_4` varchar(100) DEFAULT NULL, `contacts_i_5` varchar(100) DEFAULT NULL, `contacts_i_6` varchar(100) DEFAULT NULL, `contacts_i_7` varchar(100) DEFAULT NULL, `contacts_i_8` varchar(100) DEFAULT NULL, `contacts_i_9` varchar(100) DEFAULT NULL, `contacts_i_10` varchar(100) DEFAULT NULL, `contacts_i_11` varchar(100) DEFAULT NULL, `contacts_i_12` varchar(100) DEFAULT NULL, `contacts_i_13` varchar(100) DEFAULT NULL, `contacts_i_14` varchar(100) DEFAULT NULL, `contacts_i_15` varchar(100) DEFAULT NULL, PRIMARY KEY (`contact_id`), KEY `contact_campaign_id` (`contact_campaign_id`), KEY `contact_client_id` (`contact_client_id`), KEY `contact_purl2` (`contact_purl2`), KEY `contact_purl1` (`contact_purl1`), KEY `contact_purl` (`contact_purl`) )

Recientemente optimicé y desfragmentaron la tabla también.

¿Alguna idea sobre qué estaría causando esto?


Primero, gracias por publicar la estructura de la tabla, la consulta y el resultado de EXPLAIN en su pregunta. Creo que está cruzando el límite de tamaño de tabla temporal de memoria / disco, por lo tanto, el gran cambio de rendimiento. Si coloca un índice único en la columna contact_purl, MySQL no permitirá la inserción de duplicados. Esto haría innecesaria su consulta. De lo contrario, crearía un índice en (contact_client_id, contact_purl) para que MySQL pueda averiguar qué filas desea de los índices directamente. También puede intentar separar la búsqueda de las columnas y recuperarlas mediante una subconsulta. Algo como esto tal vez:

SELECT contact_purl, contact_firstName, contact_lastName, contact_id FROM contacts, (SELECT MIN(contact_id) AS MinID FROM contacts WHERE contact_client_id = 1 GROUP BY contact_purl HAVING COUNT( contact_id ) > 1) nodups WHERE nodups.MinID = contacts.contact_id