Hi,
I have an SQL query which gets clients’ info from the DB, by joining some tables. It returns the desired data fine.
My problem is that the query started to take considerably longer to load as the number of DB entries grow (around 2000 clients now). How long it takes varies, but it sometimes takes up to 10 or 15 seconds, which is not acceptable.
Before considering removing some tables, hence simplfying the query, I am looking for ideas to improve the query speed in whatever ways possible.
I guess my tables could use some key indexes? I am not much experienced with using indexes properly, so any recommendation for which kind of index should be used for which column would be great.
My query:
SELECT clients.id, fname, lname, email, clients.phone, city, state, zip, address, notes, added, started, abbr, statuses.name AS status, filters FROM clients
LEFT JOIN states ON clients.state = states.id
LEFT JOIN client_statuses ON clients.id = client_statuses.client_id
LEFT JOIN statuses ON statuses.id = client_statuses.status_id
LEFT JOIN (SELECT client_filters.client_id, GROUP_CONCAT(filters.name,',',filters.type SEPARATOR ':') AS filters FROM client_filters
INNER JOIN filters ON filters.id = client_filters.filter_id
GROUP BY client_filters.client_id) SQ ON SQ.client_id = clients.id
LEFT JOIN client_filters ON clients.id = client_filters.client_id
WHERE active = 1 GROUP BY clients.id ORDER BY added DESC LIMIT 0, 20
My tables:
CREATE TABLE `clients` (
`id` int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
`fname` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`lname` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`phone` bigint(10) UNSIGNED DEFAULT NULL,
`city` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`state` int(2) DEFAULT NULL,
`zip` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL,
`address` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`notes` text COLLATE utf8_unicode_ci,
`added` datetime NOT NULL,
`started` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `phone` (`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `client_filters` (
`id` int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
`client_id` int(7) UNSIGNED NOT NULL,
`filter_id` int(5) UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `client_statuses` (
`id` int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
`client_id` int(7) UNSIGNED NOT NULL,
`status_id` int(2) UNSIGNED NOT NULL,
`user_id` int(7) UNSIGNED NOT NULL,
`active` int(1) UNSIGNED NOT NULL DEFAULT '1',
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `filters` (
`id` int(5) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`type` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC;
CREATE TABLE `states` (
`id` int(2) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`abbr` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`phone` bigint(10) DEFAULT NULL,
`google` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`yelp` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`served` int(1) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `statuses` (
`id` int(2) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Thanks for your opinions.