优化mysql慢速查询
向数据库中添加的记录越多,查询速度就越慢。从1秒开始。到现在几秒钟,结果网页加载时间太长了优化mysql慢速查询,mysql,indexing,subquery,query-optimization,Mysql,Indexing,Subquery,Query Optimization,向数据库中添加的记录越多,查询速度就越慢。从1秒开始。到现在几秒钟,结果网页加载时间太长了 CREATE TABLE `ads` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `user_status` enum('register','unregister') COLLATE latin1_general_ci NOT NULL DEFAULT 'register',
CREATE TABLE `ads` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`user_status` enum('register','unregister') COLLATE latin1_general_ci NOT NULL DEFAULT 'register',
`title` varchar(255) COLLATE latin1_general_ci NOT NULL,
`tags` varchar(255) COLLATE latin1_general_ci NOT NULL,
`ad_type` enum('offer','want') COLLATE latin1_general_ci NOT NULL,
`price` float NOT NULL,
`image` varchar(255) COLLATE latin1_general_ci NOT NULL,
`address` varchar(255) COLLATE latin1_general_ci NOT NULL,
`google_address` varchar(255) COLLATE latin1_general_ci NOT NULL,
`country_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`address2` text COLLATE latin1_general_ci NOT NULL,
`city` varchar(255) COLLATE latin1_general_ci NOT NULL,
`location` int(11) NOT NULL,
`postal_code` varchar(255) COLLATE latin1_general_ci NOT NULL,
`Latitude` varchar(255) COLLATE latin1_general_ci NOT NULL,
`Longitude` varchar(255) COLLATE latin1_general_ci NOT NULL,
`working_remote` varchar(255) COLLATE latin1_general_ci NOT NULL,
`emergency_service` varchar(255) COLLATE latin1_general_ci NOT NULL,
`ad_description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`cat_id` int(11) NOT NULL,
`sub_cat_id` int(11) NOT NULL,
`sub_sub_cat_id` int(11) NOT NULL,
`status` enum('0','1') COLLATE latin1_general_ci NOT NULL,
`delete_status` enum('0','1') COLLATE latin1_general_ci NOT NULL DEFAULT '0',
`publication_days` varchar(255) COLLATE latin1_general_ci NOT NULL,
`publication_total` float(11,2) NOT NULL,
`added_date` datetime NOT NULL,
`expiry_date` datetime NOT NULL,
`payment_status` enum('pending','paid','cancel') COLLATE latin1_general_ci NOT NULL,
`closed_date` datetime NOT NULL,
`deleted_date` datetime NOT NULL,
`ad_status` enum('active','closed') COLLATE latin1_general_ci NOT NULL DEFAULT 'active',
`user_first_name` varchar(255) COLLATE latin1_general_ci NOT NULL,
`user_last_name` varchar(255) COLLATE latin1_general_ci NOT NULL,
`user_phone_number` varchar(255) COLLATE latin1_general_ci NOT NULL,
`user_email_id` varchar(255) COLLATE latin1_general_ci NOT NULL,
`ads_extend_date` datetime NOT NULL,
`ads_extend_expiry_date` datetime NOT NULL,
`ads_extend_status` enum('yes','no') COLLATE latin1_general_ci NOT NULL DEFAULT 'no',
`actvation_notification` enum('yes','no') COLLATE latin1_general_ci NOT NULL DEFAULT 'no',
`ads_view_count` int(11) NOT NULL,
`md5_key` varchar(100) COLLATE latin1_general_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`,`user_status`,`title`,`ad_type`,`price`),
KEY `title` (`title`),
KEY `ad_type` (`ad_type`),
KEY `price` (`price`),
KEY `google_address` (`google_address`),
KEY `country_id` (`country_id`),
KEY `state_id` (`state_id`),
KEY `city` (`city`),
KEY `postal_code` (`postal_code`),
KEY `cat_id` (`cat_id`),
KEY `sub_cat_id` (`sub_cat_id`),
KEY `sub_sub_cat_id` (`sub_sub_cat_id`),
KEY `status` (`status`),
KEY `payment_status` (`payment_status`),
KEY `ad_status` (`ad_status`),
KEY `added_date` (`added_date`),
KEY `expiry_date` (`expiry_date`),
KEY `id_2` (`id`,`user_id`,`user_status`,`title`,`ad_type`,`country_id`,`state_id`,`city`,`postal_code`,`cat_id`,`sub_cat_id`,`sub_sub_cat_id`,`added_date`,`expiry_date`,`payment_status`,`ad_status`)
) ENGINE=MyISAM AUTO_INCREMENT=1208 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
慢速查询日志
# Query_time: 3.859838 Lock_time: 0.000368 Rows_sent: 340 Rows_examined: 1248768
SET timestamp=1448331158;
SELECT ads.id,ads.user_id, ads.user_status, ads.title, ads.ad_type,ads.price, ads.address, ads.google_address, ads.state_id, ads.address2, ads.city as city_id, ads. location as location_id, ads.postal_code, ads.Latitude, ads.Longitude, ads.working_remote, ads.emergency_service, ads.ad_description, ads.cat_id, ads. sub_cat_id, ads.sub_sub_cat_id, ads.status, ads.publication_total, ads.ads_view_count, ads.added_date,cat.category_name, sub_cat.category_name as sub_category_name, sub_sub_cat.category_name as sub_sub_category_name, usr.id as user_id, usr.username as user_name, usr.first_name as first_name, usr.rating as rating, adimg.thumbnail, state.state,state.state_abbr, city.city, location.location as locationname,
(SELECT added_date
FROM ads_publication as pub
WHERE pub.ad_id = ads.id
AND pub.publication_id != '0'
ORDER BY pub.sort_type ASC LIMIT 0,1) as publication_srt_id,
SQRT((((69.1*(ads.Latitude -(0)))*(69.1*(ads.Latitude -(0))))+((53*(ads.Longitude -(0)))*(53*(ads.Longitude -(0)))))) as dist_in_miles
FROM ads as ads
LEFT JOIN ads_images as adimg ON (ads.id = adimg.ad_id AND default_image = '1')
LEFT JOIN workrange as wr ON ads.user_id = wr.user_id
LEFT JOIN users as usr ON ads.user_id = usr.id
LEFT JOIN ads_service as price_list ON ads.id = price_list.ad_id
LEFT JOIN ads_publication as promot ON ads.id = promot.ad_id
LEFT JOIN user_languages as language ON ads.id = language.ad_id
LEFT JOIN categories as cat ON (ads.cat_id = cat.id AND cat.parent_category_id = 0)
LEFT JOIN categories as sub_cat ON ads.sub_cat_id = sub_cat.id
LEFT JOIN categories as sub_sub_cat ON ads.sub_sub_cat_id = sub_cat.id
LEFT JOIN location as state ON ads.state_id = state.locationId
LEFT JOIN location as city ON ads.city = city.locationId
LEFT JOIN location as location ON ads.location = location.locationId
WHERE ads.status = '1'
AND ads.payment_status = 'paid'
AND ads.delete_status = '0'
AND ads.expiry_date >= '2015-11-23 21:12:38'
AND ads.ad_status = 'active'
AND ads.ad_type = 'offer'
GROUP BY ads.id
ORDER BY ads.user_status ASC, publication_srt_id DESC, ads.added_date DESC;
说明
id | select_type |table | type | possible_keys | key | key_len | ref | rows | Extra
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 | PRIMARY | ads | index_merge | "ad_type,status,payment_status,ad_status,expiry_dat..." | "status,ad_status" | "1,1" | NULL | 173 | "Using intersect(status,ad_status); Using where; Us..."
1 | PRIMARY | adimg | index | NULL | id | 526 | NULL | 1398 | Using index
1 | PRIMARY | wr | ALL | NULL | NULL | NULL | NULL | 75 |
1 | PRIMARY | usr | eq_ref | PRIMARY | PRIMARY | 4 | serv_co_za.ads.user_id | 1 |
1 | PRIMARY | price_list | ALL | NULL | NULL | NULL | NULL | 57 |
1 | PRIMARY | promot | ref | "ad_id,ad_id_2,ad_id_3" | ad_id_3 | 4 | serv_co_za.ads.id | 11 | Using index
1 | PRIMARY | language | ALL | NULL | NULL | NULL | NULL | 393 |
1 | PRIMARY | cat | eq_ref | "PRIMARY,id" | PRIMARY | 4 | serv_co_za.ads.cat_id | 1 |
1 | PRIMARY | sub_cat | eq_ref | "PRIMARY,id" | PRIMARY | 4 | serv_co_za.ads.sub_cat_id | 1 |
1 | PRIMARY | state | eq_ref | PRIMARY | PRIMARY | 4 | serv_co_za.ads.state_id | 1 |
1 | PRIMARY | city | eq_ref | PRIMARY | PRIMARY | 4 | serv_co_za.ads.city | 1 |
1 | PRIMARY | location | eq_ref | PRIMARY | PRIMARY | 4 | serv_co_za.ads.location | 1 |
1 | PRIMARY | sub_sub_cat | index | NULL | id | 111 | NULL | 1193 | Using index
2 | DEPENDENT SUBQUERY | pub | ref | "ad_id,ad_id_2,ad_id_3" | ad_id | 4 | func | 115 | Using where; Using filesort
配置:
key_buffer_size 33554432
max_allowed_packet 268435456
query_cache_limit 1048576
query_cache_min_res_unit 4096
query_cache_size 33554432
myisam_sort_buffer_size 16777216
sort_buffer_size 524288
thread_cache_size 4
thread_concurrency 10
interactive_timeout 28800
wait_timeout 28800
我注意到的是,当这个部分从查询的末尾被删除时
GROUP BY ads.id ORDER BY ads.user_status ASC, publication_srt_id DESC, ads.added_date DESC;
查询时间约为0.06秒
非常感谢您的帮助或出发点
提前谢谢大家,,
德里克使用intersect(状态,ad_状态)
——一个综合指数将永远战胜这一点。因此,添加索引(状态、广告状态)
。假设这些列只是标志,就去掉它们上的单个索引。(去掉其他状态字段上的其他简单索引。)
对于中的,这样更好:
INDEX(status, payment_status, delete_status, ad_status, at_type, -- in any order
expiry_date) -- deliberately last
这将使第一步更有效率。解释了我是怎么做到的
删除LEFT
,除非“right”表确实是可选的。这可以让优化器在计算查询时有更多的选择
wr
、price\u list
和language
需要扫描所有行。让我们找出原因。他们需要分别在user\u id
、ad\u id
和ad\u id
上建立索引。并且数据类型必须与所比较的数据类型相匹配
不要在float
或DOUBLE
中使用(M,N)
(例如,float(11,2)
),这会导致额外的舍入,可能会导致意外。对于货币,切换到十进制(11,2)
(或类似)
不要将VARCHAR
用于连续的数值,如纬度和经度FLOAT
或DOUBLE
很好
考虑迁移到InnoDB。MyISAM快死了
删除索引id_2——它可能没有任何作用
查询速度越来越慢的可能原因:
wr
、price\u list
和语言
越来越大。指数应该可以解决这个问题
- MyISAM涉及表锁
- 键缓冲区大小应设置为可用ram的20%左右。随着表的增长,键缓冲区可能会抖动。(注意:InnoDB需要不同的设置。)
((编辑))
- 由于Latitude需要转换为表达式求值,因此使用一些数字数据类型更为重要
pub
需要索引(广告id、分类类型)
publication_id
可能会妨碍上述索引
;你能取消考试吗
使用intersect(状态,ad_状态)
——一个综合指数将永远击败它。因此,添加索引(状态、广告状态)
。假设这些列只是标志,就去掉它们上的单个索引。(去掉其他状态字段上的其他简单索引。)
对于中的,这样更好:
INDEX(status, payment_status, delete_status, ad_status, at_type, -- in any order
expiry_date) -- deliberately last
这将使第一步更有效率。解释了我是怎么做到的
删除LEFT
,除非“right”表确实是可选的。这可以让优化器在计算查询时有更多的选择
wr
、price\u list
和language
需要扫描所有行。让我们找出原因。他们需要分别在user\u id
、ad\u id
和ad\u id
上建立索引。并且数据类型必须与所比较的数据类型相匹配
不要在float
或DOUBLE
中使用(M,N)
(例如,float(11,2)
),这会导致额外的舍入,可能会导致意外。对于货币,切换到十进制(11,2)
(或类似)
不要将VARCHAR
用于连续的数值,如纬度和经度FLOAT
或DOUBLE
很好
考虑迁移到InnoDB。MyISAM快死了
删除索引id_2——它可能没有任何作用
查询速度越来越慢的可能原因:
wr
、price\u list
和语言
越来越大。指数应该可以解决这个问题
- MyISAM涉及表锁
- 键缓冲区大小应设置为可用ram的20%左右。随着表的增长,键缓冲区可能会抖动。(注意:InnoDB需要不同的设置。)
((编辑))
- 由于Latitude需要转换为表达式求值,因此使用一些数字数据类型更为重要
pub
需要索引(广告id、分类类型)
publication_id
可能会妨碍上述索引
;你能取消考试吗
您的格式设置确实使这成为一个不希望回答的问题,但我似乎在您的SELECT
语句中看到了一个子查询。如果您删除此项(可能是通过联接),您可能会得到性能提升。很抱歉,格式设置有所改进,感谢您的提示。您的格式设置确实使这成为一个不希望回答的问题,但我似乎在您的SELECT
语句中看到了一个子查询。如果你删除这个,可能是通过加入,你可能会得到性能提升。很抱歉格式化,它已经改进了,谢谢你的提示。谢谢你@Rick,看起来在我面前还有很多工作要做。再次谢谢你,瑞克,看来我面前还有很多工作要做。又是Thx。