A rare initial practice of MySQL optimization

Last year, the project was refactored, the system was switched to a micro-service architecture, and some aspects of the database have also done some practice of sub-database and sub-table. I feel that writing code during that time was hearty and refreshing. Of course, the old system still needs to continue to be maintained, depending on the current situation, Both systems will likely be available to users simultaneously in the next few years. We have no opinion on development, everything serves the operation (inner OS: can the product and operation majors promote the switch as soon as possible, after all, the old way of writing JSP, which is sour and difficult to understand).

On this day, the boss lost a slow query SQL statement, saying that this SQL statement in the old system service has been queried for more than 4s+, and see where it is used in the business and confirm whether there is room for optimization. The specific query statement example is as follows (business Security issues, cannot be displayed to the public):

select o.attr1,o.attr2,o.attr3, u.attr4, u.attr5 from order o outer join user u on 
o.u_id=u.id and o.createAt>='2022-03-20 00:00:00' and o.status="success" and o.feeType='TV' and o.payType='ali_pay' ....
复制代码

The main function of this service is to regularly update user membership subscription rights from three parties every 5s. Ok, I took the task and started to execute it on the test environment to check the execution plan of the SQL statement.

id  select_type table   type        possible_key    key      key_len ref         rows   Extra
1	SIMPLE	    this_	index	                	PRIMARY 	4		           56	Using where
1	SIMPLE	    user2_	eq_ref	    PRIMARY	        PRIMARY	    4	this_.user_id	1	Using where
复制代码

The test environment is that there are only more than 50 test order data. It seems that although the primary key index is used, the rows range is the entire table. This is mainly because the query statement is sorted in descending order according to the id of the order table, and the sorting can be removed. It can be seen that it is actually a full table scan:

id  select_type table   type        possible_key    key      key_len ref         rows   Extra
1	SIMPLE	    this_	index	                	PRIMARY 	4		           56	Using where
1	SIMPLE	    user2_	eq_ref	    PRIMARY	        PRIMARY	    4	this_.user_id	1	Using where
复制代码

Well, let the operation and maintenance confirm the data of the order form table on the existing network, which reaches 340W+, and the query time reaches 4.737s. At this level, the full table scan is unacceptable, and the current amount of more than 1W continues to increase every day. In this case, the query must be optimized. To optimize the first C bit, the index must be used. At present, in addition to the default id primary key, the order table has an index on the user_id field for business related queries. However, for the current requirement, the scanning range cannot be effectively reduced, and a new index needs to be considered. Determine what kind of index to create?

  1. There are multiple conditions in the query conditions: status (order status), payType (payment type) feeType (billing type) createAt (order creation time), except for createAt, other fields are enumeration type values, according to the index creation principle , the field of enumeration value type is naturally inappropriate, so createAt is the best field to create an index
  2. Based on the existing business, consider whether the created index can serve more business needs? Reorganize the entire service application as a whole, and the order table also has the following applications:
    • Query the payment success of a certain time range of the channel (1, the application frequency is low, mainly used for back-end query operations)
    • 查询某个用户TV付费服务类型订购成功记录(1处,定时每30s执行一次)
    • 根据时间范围查询TV端订购记录(1处,定时每30s执行一次)

所以结合具体的业务形态,决定使用复合索引进一步来提升索引复用和查询共用能力。 索引创建如下:

alter table order add index time_user_status_idx(createAt,user_id,status)
复制代码

确定了处理思路,找老大讨论了一下,比较服务目前的业务情况,那就和晚上的服务上线一并处理了,凌晨12点,运维同学传来捷报,执行时间为0.001s,OK,收工。 虽然这次的优化不是非常深入,但是也确实明白了业务中当数据量上来后性能优化的重要性。未来的开发路漫长,需要多多思考。

Guess you like

Origin juejin.im/post/7077917522439176228