2014-03-27 56 views
0

大家好我有一個MySQL查詢從多個表中提取數據。這裏是我的查詢MySQL查詢優化改進

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 

它從用戶表,服務表,評論表和供應商圖片表中獲取數據。它也可以工作,但執行時間非常緩慢。我想讓它成爲一個單一的查詢,並避免內部的五個查詢可能運行得很快。任何幫助?

表結構。

-- 
-- 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 ; 
+1

如果您希望我們幫助優化查詢,您需要向我們展示表格和索引定義**以及每個表格的行數。也許你的表格定義不好。也許索引沒有正確創建。也許你沒有一個你認爲你做過的那個專欄的索引。沒有看到表和索引定義,我們不能說。我們還需要行計數,因爲這會大大影響查詢優化。如果你知道如何做一個'EXPLAIN'或者得到一個執行計劃,那就把結果也放在問題中。如果您沒有索引,請儘快訪問http://use-the-index-luke.com。 –

+0

您是否嘗試在這些表中使用'LEFT JOIN'而不是在SELECT中添加子查詢?還提供表格中索引和記錄數量的詳細信息。 – Slowcoder

+0

@AndyLester這個查詢得到結果,所以第一件事就是確定表中有索引,第二件事是用戶表中的行數是321,查看錶115服務表723提供者圖片表239,並且這些表中的每一個都有user_id作爲與用戶表關聯的外鍵。 –

回答

1

您可能只需添加索引即可加快查詢速度。嘗試添加以下指標:

service(user_id, service_price) 
providerphoto(user_id, providerphoto_order) 
review(user_id, review_rate) 
+0

我改變了表格並添加了這些索引,但它不起作用。 –

+0

@devdesign。 。 。我覺得很驚訝。我將註釋掉五個子查詢,然後將它們一次添加到一個子查詢中,以確定性能問題發生的位置。 –

0

我會做的第一件事是指數user.user_typeuser.user_deleteduser.user_active讓優化器迅速用較小的一套user記錄開始不得不應對。

是否允許service.user_id爲NULL?這似乎是一個錯誤。

另外,你可能想要在你正在做ORDER BY的任何列上拋出索引。

找出此查詢中速度較慢的最佳方法是進行EXPLAIN QUERY並分析它告訴您的內容。我們也可以幫助你。

+0

沒有service.user_id不能爲空。你能否寫出你認爲最好的查詢? –

+0

找出此查詢中速度緩慢的最佳方法是執行EXPLAIN QUERY並分析它告訴您的內容。我們也可以幫助你。 –

1

就是這樣。這將返回用戶的所有值,因爲我在查詢中沒有使用ORDERLIMIT。這只是爲了方法。

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; 
+0

這隻返回一行。但是,如果從字段中刪除MIN和ROUND(AVG),它將返回200條記錄,並且比使用內部SELECT查詢的原始查詢的速度更快,但由於原始查詢返回的查詢是正確的,因此記錄缺少38行。 –