Unable to change query values in wordpress query.php - mysql

My website having woo commerce theme is very slow in loading specially product summary page takes almost 3 minutes in loading.Now i want to change product summary page main query but unable to find way so that i will be able to change/optimize my query.Query output value is given below.I change $query in Query.php but when i execute page then there is no change in query and it is showing same query.Please guide if any other change is necessary.
Previous and new values in query.php are given below.
Previous value
$query = $wpdb->prepare("SELECT post_id
FROM $wpdb->postmeta, $wpdb->posts
WHERE ID = post_id
AND post_type = %s
AND meta_key = '_wp_old_slug'
AND meta_value = %s",
$post_type, $wp_query->query_vars['name']);
New value(want to use this value instead of above)
$query = $wpdb->prepare("SELECT post_id
FROM $wpdb->postmeta, $wpdb->posts
WHERE ID = post_id" );
Query value used for page data
SELECT SQL_CALC_FOUND_ROWS wp_bkkf_posts.ID
FROM wp_bkkf_posts
INNER JOIN wp_bkkf_postmeta
ON ( wp_bkkf_posts.ID = wp_bkkf_postmeta.post_id )
WHERE 1=1
AND ( ( wp_bkkf_postmeta.meta_key = '_visibility'
AND wp_bkkf_postmeta.meta_value IN ('visible','catalog') ) )
AND wp_bkkf_posts.post_type = 'product'
AND (wp_bkkf_posts.post_status = 'publish'
OR wp_bkkf_posts.post_status = 'private')
GROUP BY wp_bkkf_posts.ID
ORDER BY wp_bkkf_posts.menu_order ASC, wp_bkkf_posts.post_title ASC
LIMIT 0, 12
Actually i don't want to use following values in query.
AND ( ( wp_bkkf_postmeta.meta_key = '_visibility'
AND wp_bkkf_postmeta.meta_value IN ('visible','catalog') ) )
AND wp_bkkf_posts.post_type = 'product'
AND (wp_bkkf_posts.post_status = 'publish'
OR wp_bkkf_posts.post_status = 'private')
Show create table output is given below
CREATE TABLE `wp_bkkf_postmeta` (
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`meta_key` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meta_value` longtext COLLATE utf8mb4_unicode_ci,
PRIMARY KEY (`meta_id`),
KEY `post_id` (`post_id`),
KEY `meta_key` (`meta_key`(191))
) ENGINE=MyISAM AUTO_INCREMENT=30883570 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE `wp_bkkf_posts` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_author` bigint(20) unsigned NOT NULL DEFAULT '0',
`post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_content` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`post_title` text COLLATE utf8mb4_unicode_ci NOT NULL,
`post_excerpt` text COLLATE utf8mb4_unicode_ci NOT NULL,
`post_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'publish',
`comment_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
`ping_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open',
`post_password` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`post_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`to_ping` text COLLATE utf8mb4_unicode_ci NOT NULL,
`pinged` text COLLATE utf8mb4_unicode_ci NOT NULL,
`post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_content_filtered` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`post_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
`guid` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`menu_order` int(11) NOT NULL DEFAULT '0',
`post_type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'post',
`post_mime_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`comment_count` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `post_name` (`post_name`(191)),
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
KEY `post_parent` (`post_parent`),
KEY `post_author` (`post_author`),
KEY `post_idx` (`post_type`,`post_status`)
) ENGINE=MyISAM AUTO_INCREMENT=1556181 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
If anyone have idea regarding $query value change then please guide,also please share other file names where change required..thanks.

SELECT MAX(CHAR_LENGTH(meta_key)) FROM wp_bkkf_postmeta;
If that comes out less than 191, then do these:
ALTER TABLE wp_bkkf_postmeta
MODIFY `meta_key` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
DROP KEY `post_id`,
ADD INDEX pm (post_id, meta_key);
Consider getting rid of SQL_CALC_FOUND_ROWS; it probably is a slowdown. However losing that will lose the "out of ..." clause on the page.
If you toss the entire WHERE then the JOIN and GROUP BY can go away, too:
SELECT SQL_CALC_FOUND_ROWS wp_bkkf_posts.ID
FROM wp_bkkf_posts
ORDER BY wp_bkkf_posts.menu_order ASC, wp_bkkf_posts.post_title ASC
LIMIT 0, 12
That will run faster. Still, it will need to scan the entire 1.5 million row table. Why you would want that particular ORDER BY?

Related

MySQL Join 1 to 1 in N items table

I need some help on my shop database structure. To fetch items from category, there are already some joins, but i would like to add an image to an item, from other table. Main items table doesn't have an image id, so we just get one from other table by it's weight = 1.
So, there is a structure:
CREATE TABLE IF NOT EXISTS `categories` (
`category_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255)
CHARACTER SET utf8mb4 DEFAULT NULL
COMMENT 'Category title',
`parent_id` INT(11) NOT NULL DEFAULT '0'
COMMENT 'Category Parent ID',
`status` TINYINT(1) DEFAULT '0'
COMMENT 'Category active status',
`weight` INT(11) DEFAULT '0',
`slug` VARCHAR(255)
CHARACTER SET utf8mb4 DEFAULT NULL
COMMENT 'Category url alias',
PRIMARY KEY (`category_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `items` (
`item_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255)
CHARACTER SET utf8mb4 NOT NULL DEFAULT ''
COMMENT 'Item name',
`description` TEXT CHARACTER SET utf8mb4 NOT NULL
COMMENT 'Item description',
`user_id` INT(11) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'User id',
`category_id` INT(11) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'Category id',
`price` DECIMAL(10, 2) NOT NULL DEFAULT '0.00'
COMMENT 'Item price',
`status` INT(1) UNSIGNED NOT NULL DEFAULT '1'
COMMENT 'Item status',
`deleted` INT(1) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'Delite status',
`blocked` INT(1) UNSIGNED NOT NULL DEFAULT '0'
COMMENT 'Block status',
PRIMARY KEY (`item_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `items_images` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`file` VARCHAR(255)
CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
`weight` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`status` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
`deleted` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
`created` INT(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci
ROW_FORMAT = COMPACT;
As you can see from there, category structure also contain parent_id inside, so we can always get the category tree.
Using this query is working as well and really fast.
SELECT
`i`.*,
`c1`.`name` AS `category_name`,
`c1`.`slug` AS `category_slug`,
`c2`.`name` AS `subcategory_name`,
`c2`.`slug` AS `subcategory_slug`
FROM `items` AS `i`
LEFT JOIN `categories` AS `c2` ON `c2`.`category_id` = `i`.`category_id`
LEFT JOIN `categories` AS `c1` ON `c1`.`category_id` = `c2`.`parent_id`
WHERE `i`.`deleted` = 0 AND `i`.`blocked` = 0 AND `i`.`status` = 1
ORDER BY `i`.`created` DESC
LIMIT 40
But, if i join items_images like:
SELECT
`i`.*,
`ii`.`file` AS `image`,
`c1`.`name` AS `category_name`,
`c1`.`slug` AS `category_slug`,
`c2`.`name` AS `subcategory_name`,
`c2`.`slug` AS `subcategory_slug`
FROM `items` AS `i`
LEFT JOIN `items_images` AS `ii`
ON `i`.`item_id` = `ii`.`item_id` AND `ii`.`weight` = 1
AND `ii`.`status` = 1 AND `ii`.`deleted` = 0
LEFT JOIN `categories` AS `c2` ON `c2`.`category_id` = `i`.`category_id`
LEFT JOIN `categories` AS `c1` ON `c1`.`category_id` = `c2`.`parent_id`
WHERE `i`.`deleted` = 0 AND `i`.`blocked` = 0 AND `i`.`status` = 1
ORDER BY `i`.`created` DESC LIMIT 40
Sometimes it takes up to 1 minute on 14k items with 40k images.
Is there something i can improve?! Please note, there might be items without images too. That is not requirement.
Small addition. Even single images join on items makes the query run over a minute. here a sample:
SELECT `i`.*, `ii`.`file` AS `image` FROM `items` AS `i`
LEFT JOIN `items_images` AS `ii` ON `i`.`item_id` = `ii`.`item_id`
AND `ii`.`weight` = 1 AND `ii`.`status` = 1 AND `ii`.`deleted` = 0
WHERE `i`.`deleted` =0 AND `i`.`sold` =0 AND `i`.`blocked` =0 AND `i`.`status` = 1
ORDER BY `i`.`created` DESC
You have inconsistency in naming convention.
Index parent_id
ALTER TABLE categories ADD INDEX parent_id_ind (parent_id ASC) ;
Try to run your query again.
In databases you would use indexes to improve the speed of data retrieval. An index is typically created on columns used in JOIN, WHERE, and ORDER BY clauses.
I suggest you to improve your structure, you can take it or leave it,
Here my suggestion:
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'Category title',
`category_id` int(11) NOT NULL DEFAULT '0' COMMENT 'Category Parent ID',
`status` enum('status1','status2') COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Category active status',
`weight` int(11) DEFAULT '0',
`slug` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'Category url alias',
PRIMARY KEY (`id`),
KEY `category_id_ind` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT 'Item name',
`description` text CHARACTER SET utf8mb4 NOT NULL COMMENT 'Item description',
`user_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'User id',
`category_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Category id',
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT 'Item price',
`status` enum('status1','status2') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'status1' COMMENT 'Item status',
`is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'Delite status',
`is_blocked` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'Block status',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `item_images`;
CREATE TABLE `item_images` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`item_id` int(10) unsigned NOT NULL DEFAULT '0',
`file_path` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL ,
`weight` int(11) unsigned NOT NULL DEFAULT '0',
`status` tinyint(1) unsigned NOT NULL DEFAULT '0',
`is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
`creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPACT;
Add composite indexes:
items: INDEX(deleted, blocked, status, created) -- created must be last
items_images: INDEX(item_id, weight, status, deleted)
categories: INDEX(category_id, deleted, blocked, status)
Except as noted, the order of columns is not important.
Remove LEFT unless you see a need for it.
Please provide EXPLAIN SELECT ....
The likely reason for the sluggishness is having to check lots of image rows for weight=1. On top of that, the lack of any useful index means a costly table scan.

MYSQL Multiple tables left joins with conditions and duplicate tables

I can't seem to produce a valid MySQL (version MySQL 5.6).
I have the bellow SQL that works well but it returns records only when all conditions are satisfied. I need it to return records for all users having the missing data as NULL.
So LEFT JOINS would be the way (unless there is a better way).
Please note about the usage of one of the tables twice.
SELECT
users.email,
ufs.first_name,
ufs.last_name,
country_label.label as country,
interest_label.label as interest,
points.actions,
points.badges,
points.points
FROM
site_users users,
site_user_fields_values interest,
site_user_fields_options interest_label,
site_user_fields_values country,
site_user_fields_options country_label,
points_users points,
site_user_fields_search ufs
WHERE
interest.field_id = 15 AND
country.field_id = 16 AND
users.user_id = interest.item_id AND
interest.value = interest_label.option_id AND
users.user_id = country.item_id AND
country.value = country_label.option_id AND
users.user_id = points.ref_id AND
users.user_id = ufs.item_id;
That produces:
array(size = 2)
0 =>
array(size = 8)
'email' => string 'info#mygreatsite.com'
'first_name' => string 'Filip'
'last_name' => string 'Moore'
'country' => string 'United Kingdom'
'interest' => string 'Fishing'
'actions' => string '53'
'badges' => string '4'
'points' => string '21.00'
1 =>
array(size = 8)
'email' => string 'user#mygreatsite.com'
'first_name' => string 'Peter'
'last_name' => string 'Smith'
'country' => string 'Spain'
'interest' => string 'Swimming'
'actions' => string '44'
'badges' => string '5'
'points' => string '212.00'
And here are the CREATE TABLE statements of all tables involved:
CREATE TABLE `site_users` (
`user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`username` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
`displayname` varchar(128) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`photo_id` int(11) unsigned NOT NULL DEFAULT '0',
`password` char(32) COLLATE utf8_unicode_ci NOT NULL,
`salt` char(64) COLLATE utf8_unicode_ci NOT NULL,
`locale` varchar(16) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT 'auto',
`language` varchar(8) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT 'en_US',
`enabled` tinyint(1) NOT NULL DEFAULT '1',
`creation_date` datetime NOT NULL,
`modified_date` datetime NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `EMAIL` (`email`),
UNIQUE KEY `USERNAME` (`username`),
KEY `CREATION_DATE` (`creation_date`),
KEY `enabled` (`enabled`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `site_user_fields_options` (
`option_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`field_id` int(11) unsigned NOT NULL,
`label` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`order` smallint(6) NOT NULL DEFAULT '999',
PRIMARY KEY (`option_id`),
KEY `field_id` (`field_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `site_user_fields_values` (
`item_id` int(11) unsigned NOT NULL,
`field_id` int(11) unsigned NOT NULL,
`index` smallint(3) unsigned NOT NULL DEFAULT '0',
`value` text COLLATE utf8_unicode_ci NOT NULL,
`privacy` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`item_id`,`field_id`,`index`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `site_user_fields_search` (
`item_id` int(11) unsigned NOT NULL,
`profile_type` smallint(11) unsigned DEFAULT NULL,
`first_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`last_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`gender` smallint(6) unsigned DEFAULT NULL,
`birthdate` date DEFAULT NULL,
`field_15` enum('4','5','6','7','8','9','10') COLLATE utf8_unicode_ci DEFAULT NULL,
`field_16` enum('11','12','13') COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`item_id`),
KEY `profile_type` (`profile_type`),
KEY `first_name` (`first_name`),
KEY `last_name` (`last_name`),
KEY `gender` (`gender`),
KEY `birthdate` (`birthdate`),
KEY `field_15` (`field_15`),
KEY `field_16` (`field_16`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `points_users` (
`user_id` int(11) unsigned NOT NULL auto_increment,
`ref_id` int(11) unsigned NOT NULL,
`actions` int(11) unsigned DEFAULT 0,
`badges` int(11) unsigned DEFAULT 0,
`points` FLOAT(12) unsigned DEFAULT 0,
`creation_date` DATETIME DEFAULT '00-00-00 00:00:00',
`modified_date` DATETIME DEFAULT '00-00-00 00:00:00',
PRIMARY KEY (`user_id`),
KEY `ref_id` (`ref_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
I would be very thankful for your help.
You already gave the right hint with LEFT JOIN yourself. So, it could be as easy as
SELECT
users.email,
ufs.first_name,
ufs.last_name,
country_label.label as country,
interest_label.label as interest,
points.actions,
points.badges,
points.points
FROM site_users users
LEFT JOIN site_user_fields_values interest ON users.user_id = interest.item_id
LEFT JOIN site_user_fields_options interest_label ON interest.value = interest_label.option_id
LEFT JOIN site_user_fields_values country ON users.user_id = country.item_id
LEFT JOIN site_user_fields_options country_label ON country.value = country_label.option_id
LEFT JOIN points_users points ON users.user_id = points.ref_id
LEFT JOIN site_user_fields_search ufs ON users.user_id = ufs.item_id
WHERE
interest.field_id = 15 AND
country.field_id = 16
;
Please note, however, it is currently unclear, whether this statement is really what you want (to LEFT JOIN in all cases). There might be cases, where an INNER JOIN is more appropriate. To check, we would need to discuss about foreign key relationship and/or have the CREATE TABLE statements of all the tables involved.

limit in mysql with 10K record taking too much time to execute(fail every time)

I am using MySQL database. I have a table that consist up to 75K rows of data. I am using simple query to fetch data:
select * from mytable
It works fine, shows 75k rows in few seconds. I wanted to fetch some of these data I had used limit 10000. It got stuck every time. I need to optimize MySQL query for 10k records.
I am using query like this:
select * from mytable limit 10000
Give me some solution how to execute my query fast.
my database structure is like that:
CREATE TABLE IF NOT EXISTS `mytable` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`col1` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`col2` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`col3` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`col4` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`col5` int(11) NOT NULL,
`col6` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`col7` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`col8` int(11) NOT NULL,
`col9` int(11) NOT NULL,
`col11` int(11) NOT NULL,
`col12` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`col13` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`col15` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`col16` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`col17` int(11) NOT NULL,
`col18` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`col19` enum('0','1') COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`,`col2`,`col3`,`col4`,`col5`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=75530 ;
With this solution I can fetch larger data in few seconds:
SELECT l.id,l.col1,l.col2,l.col3,l.col3,l.col4,l.col5,l.col6,l.col7
FROM (
SELECT id
FROM mytable
WHERE removed='0'
ORDER BY id
LIMIT 10000
) o
JOIN mytable ON l.id = o.id
ORDER BY l.id

MySQL query optimization improvement

Hello all I have a MySQL query that fetches data from more than on tables. Here is my query
SELECT
user_id as id,
user_name as name,
user_phone as phone,
user_email as email,
user_address1 as address1,
user_address2 as address2,
user_city as city,
user_state as state,
user_country as country,
user_available as available,
user_location as location,
user_latitude as latitude,
user_longitude as longitude,
user_description as description,
user_company as company,
user_gender as gender,
(SELECT MIN(service_price) FROM service WHERE service.user_id = a.user_id) as price,
(SELECT service_recomanded FROM service WHERE service.user_id = a.user_id ORDER BY service.service_price ASC LIMIT 1) as recomandad,
verified_email,
verified_facebook,
verified_phone,
verified_twitter,
(SELECT providerphoto_name FROM providerphoto WHERE providerphoto.user_id = a.user_id ORDER BY providerphoto_order ASC LIMIT 1 ) as photo,
(SELECT ROUND( AVG(review_rate),2) FROM review WHERE review.user_id = a.user_id ) AS rate,
(SELECT service_ICOC FROM service WHERE service.user_id = a.user_id ORDER BY service_price ASC LIMIT 1) as type
FROM
user a
WHERE a.user_type = 'provider'
AND a.user_active=1
AND a.user_deleted=0
It gets data from user table, service table, review table and providerphoto table. It works too but the execution time is very slow. I guess to make it a single query and avoid the inner five queries may run it fast. Any help?
Table structures.
--
-- Table structure for table `providerphoto`
--
CREATE TABLE IF NOT EXISTS `providerphoto` (
`providerphoto_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`providerphoto_file` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`providerphoto_name` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`providerphoto_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`providerphoto_order` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`providerphoto_id`),
KEY `user_id` (`user_id`),
KEY `providerphoto` (`user_id`,`providerphoto_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=487 ;
-- --------------------------------------------------------
--
-- Table structure for table `review`
--
CREATE TABLE IF NOT EXISTS `review` (
`review_id` int(11) NOT NULL AUTO_INCREMENT,
`review_title` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_id` int(11) NOT NULL,
`review_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`review_content` text COLLATE utf8_unicode_ci NOT NULL,
`review_user_id` int(11) NOT NULL,
`review_rate` int(10) NOT NULL DEFAULT '1',
`review_tip` int(11) NOT NULL DEFAULT '0',
`service_booked` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`review_id`),
KEY `user_id` (`user_id`),
KEY `review_date` (`review_date`),
KEY `review_user_id` (`review_user_id`),
KEY `review_rate` (`review_rate`),
KEY `review_tip` (`review_tip`),
KEY `service_booked` (`service_booked`),
KEY `review` (`user_id`,`review_rate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=97 ;
-- --------------------------------------------------------
--
-- Table structure for table `service`
--
CREATE TABLE IF NOT EXISTS `service` (
`service_id` int(11) NOT NULL AUTO_INCREMENT,
`service_name` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`service_created_by` int(11) NOT NULL DEFAULT '0',
`service_ICOC` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`service_price` int(11) NOT NULL,
`service_date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`service_date_expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`service_time` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`service_rate` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`service_type` int(10) NOT NULL DEFAULT '1' COMMENT '1-in call, 2-out call, 3-in&out call',
`service_recomanded` int(2) NOT NULL DEFAULT '0',
`service_genre` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`service_message` text COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`service_id`),
KEY `user_id` (`user_id`),
KEY `service_ICOC` (`service_ICOC`(255)),
KEY `service` (`user_id`,`service_price`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=854 ;
-- --------------------------------------------------------
--
-- Table structure for table `user`
--
CREATE TABLE IF NOT EXISTS `user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_password` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_email` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_phone` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_address1` text COLLATE utf8_unicode_ci,
`user_address2` text COLLATE utf8_unicode_ci NOT NULL,
`user_city` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_state` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_country` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_company` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_birthday` date DEFAULT NULL,
`user_register_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`user_type` enum('provider','client') COLLATE utf8_unicode_ci DEFAULT NULL,
`user_description` text COLLATE utf8_unicode_ci NOT NULL,
`user_available` int(10) NOT NULL DEFAULT '1',
`verified_email` tinyint(1) NOT NULL DEFAULT '0',
`verified_facebook` tinyint(1) NOT NULL DEFAULT '0',
`verified_phone` tinyint(1) NOT NULL DEFAULT '0',
`verified_twitter` tinyint(1) NOT NULL DEFAULT '0',
`user_facebook_friends` int(11) NOT NULL DEFAULT '0',
`user_twitter_friends` int(11) NOT NULL DEFAULT '0',
`user_longitude` decimal(10,5) NOT NULL DEFAULT '0.00000',
`user_latitude` decimal(10,5) NOT NULL DEFAULT '0.00000',
`user_deleted` tinyint(4) NOT NULL DEFAULT '0',
`user_gender` int(11) NOT NULL DEFAULT '0',
`user_facebook_token` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`user_active` tinyint(4) NOT NULL DEFAULT '1',
`user_location` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`user_push_notification_token` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`user_timezone_diff` int(11) NOT NULL DEFAULT '0',
`balanced_uri` text COLLATE utf8_unicode_ci NOT NULL,
`user_reset_passwd_token` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`is_test_user` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`),
KEY `deleted_idx` (`user_deleted`),
KEY `email_idx` (`user_email`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=426 ;
You can probably just add indexes to speed up the query. Try adding the following indexes:
service(user_id, service_price)
providerphoto(user_id, providerphoto_order)
review(user_id, review_rate)
Something like this. This will return all the values for the users as I did not use the ORDER and LIMIT in the query. This is just for the approach.
SELECT
a.user_id as id,
user_name as name,
user_phone as phone,
user_email as email,
user_address1 as address1,
user_address2 as address2,
user_city as city,
user_state as state,
user_country as country,
user_available as available,
user_location as location,
user_latitude as latitude,
user_longitude as longitude,
user_description as description,
user_company as company,
user_gender as gender,
MIN(s.service_price) as price,
s.service_recomanded as recomandad,
verified_email,
verified_facebook,
verified_phone,
verified_twitter,
pp.providerphoto_name as photo,
ROUND( AVG(r.review_rate),2) as rate,
s.service_ICOC as type
FROM
user a LEFT JOIN service s on s.user_id = a.user_id LEFT JOIN providerphoto pp on pp.user_id = a.user_id LEFT JOIN review r on r.user_id = a.user_id
WHERE a.user_type = 'provider'
AND a.user_active=1
AND a.user_deleted=0;
First thing I would do is index user.user_type, user.user_deleted and user.user_active to let the optimizer quickly start with a smaller set of user records to have to deal with.
Do you mean to allow service.user_id to be NULL? That seems like a mistake.
Also you may want to throw indexes on any columns where you're doing an ORDER BY.
The best way to find out what is slow in this query is to do a EXPLAIN QUERY and analyze what it tells you. We can help you with that as well.

Joins in MySQL are not working

I am a beginner in MySQL and trying to create a join query in MySQL.
My first SQL query is as below which displays the 2 columns votes and post
SELECT votes, post
FROM `wp_votes` where votes!=''
GROUP BY votes,post asc LIMIT 0 , 30
**Second table is where the posts are **
SELECT *
FROM `wp_posts`
LIMIT 0 , 30
What i wanna do is create a join so that it display all records from wp_posts table WHERE wp_post.ID=wp_votes.post, Also have to check if wp_votes.votes!=''
I tried the following but i am stuck on it
SELECT * FROM wp_posts join wp_votes ON wp_posts.ID =wp_votes.post
Table Structure below
CREATE TABLE IF NOT EXISTS `wp_posts` (
`ID` bigint(20) unsigned NOT NULL auto_increment,
`post_author` bigint(20) unsigned NOT NULL default '0',
`post_date` datetime NOT NULL default '0000-00-00 00:00:00',
`post_date_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
`post_content` longtext NOT NULL,
`post_title` text NOT NULL,
`post_excerpt` text NOT NULL,
`post_status` varchar(20) NOT NULL default 'publish',
`comment_status` varchar(20) NOT NULL default 'open',
`ping_status` varchar(20) NOT NULL default 'open',
`post_password` varchar(20) NOT NULL default '',
`post_name` varchar(200) NOT NULL default '',
`to_ping` text NOT NULL,
`pinged` text NOT NULL,
`post_modified` datetime NOT NULL default '0000-00-00 00:00:00',
`post_modified_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
`post_content_filtered` longtext NOT NULL,
`post_parent` bigint(20) unsigned NOT NULL default '0',
`guid` varchar(255) NOT NULL default '',
`menu_order` int(11) NOT NULL default '0',
`post_type` varchar(20) NOT NULL default 'post',
`post_mime_type` varchar(100) NOT NULL default '',
`comment_count` bigint(20) NOT NULL default '0',
PRIMARY KEY (`ID`),
KEY `post_name` (`post_name`),
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
KEY `post_parent` (`post_parent`),
KEY `post_author` (`post_author`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4570 ;
--
-- Table structure for table `wp_votes`
--
CREATE TABLE IF NOT EXISTS `wp_votes` (
`ID` int(11) NOT NULL auto_increment,
`post` int(11) NOT NULL,
`votes` text NOT NULL,
`guests` text NOT NULL,
`usersinks` text NOT NULL,
`guestsinks` text NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1052 ;
SELECT a.votes, a.post,
b.*
FROM wp_votes a
INNER JOIN wp_Post b
ON a.post = b.ID
WHERE a.votes <> ''
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins