Home Database Mysql Tutorial MySQL数据库优化的一些笔记_MySQL

MySQL数据库优化的一些笔记_MySQL

Jun 01, 2016 pm 01:49 PM
Database optimization Record

bitsCN.com

  0. 索引很重要

  之前列举记录用了下面的语句。state字段为索引。

  SELECT * FROM feed_urls WHERE state='ok' AND feed_url'' LIMIT N,10

  当记录数量很大时,有几万之后,这句SQL就很慢了。主要是因为feed_url没有建立索引。后来的解决方法是,把feed_url为空的,设为一个ok以外的state值,就行了。

  1. 索引不是万能的

  为了计算记录总数,下面的语句会很慢。

 

  mysql> SELECT COUNT(*) FROM feed_urls WHERE state='error';

  +----------+

  | COUNT(*) |

  +----------+

  | 30715 |

  +----------+

  1 row in set (0.14 sec)

  mysql> EXPLAIN SELECT COUNT(*) FROM feed_urls WHERE state='error'/G

  *************************** 1. row ***************************

  id: 1

  select_type: SIMPLE

  table: feed_urls

  type: ref

  possible_keys: state,page_index

  key: page_index

  key_len: 10

  ref: const

  rows: 25936

  Extra: Using where; Using index

  1 row in set (0.00 sec)

 

  state为索引,请求用时140ms。遍历了state='error'索引下的每一条记录。

 

  mysql> SELECT state,COUNT(*) FROM feed_urls GROUP BY state;

  +----------+----------+

  | state | COUNT(*) |

  +----------+----------+

  | error | 30717 |

  | fetching | 8 |

  | nofeed | 76461 |

  | ok | 74703 |

  | queued | 249681 |

  +----------+----------+

  5 rows in set (0.55 sec)

  mysql> EXPLAIN SELECT state,COUNT(*) FROM feed_urls GROUP BY state/G

  *************************** 1. row ***************************

  id: 1

  select_type: SIMPLE

  table: feed_urls

  type: index

  possible_keys: NULL

  key: state

  key_len: 10

  ref: NULL

  rows: 431618

  Extra: Using index

  1 row in set (0.00 sec)

 

  请求用时550ms。遍历了每个state下的每一条记录。

  改进方法:

  独立一个表用来计数,使用MySQL的Trigger同步计数:

 

  CREATE TRIGGER my_trigger AFTER UPDATE ON feed_urls

  FOR EACH ROW BEGIN

  IF OLD.state NEW.state THEN

  IF NEW.state='ok' THEN

  UPDATE feed_stat SET count_feed = count_feed + 1;

  END IF;

  IF NEW.state IN ('ok', 'error', 'nofeed') THEN

  UPDATE feed_stat SET count_access = count_access + 1;

  END IF;

  END IF;

  END

 

  2. 当分页很大时

 

  mysql> SELECT * FROM feed_urls LIMIT 230000, 1/G

  *************************** 1. row ***************************

  id: 736841f82abb0bc87ccfec7c0fdbd09c30b5a24d

  link: http://mappemunde.typepad.com/

  title: Tim Peterson

  feed_url: NULL

  update_time: 2012-05-12 11:01:56

  state: queued

  http_server: NULL

  abstract: NULL

  previous_id: ceea30e0ba609b69198c53ce71c44070d69038c5

  ref_count: 1

  error: NULL

  aid: 230001

  1 row in set (0.50 sec)

  mysql> EXPLAIN SELECT * FROM feed_urls LIMIT 230000, 1/G

  *************************** 1. row ***************************

  id: 1

  select_type: SIMPLE

  table: feed_urls

  type: ALL

  possible_keys: NULL

  key: NULL

  key_len: NULL

  ref: NULL

  rows: 431751

  Extra:

  1 row in set (0.00 sec)

 

  读取一条记录,耗时500ms,因为表记录是变长的,所以MySQL不能算出目标位置,只能每一条记录的数过去。

  改进方法:

  通过索引定位,数索引比数记录要快,因为索引占用的空间比整条记录小很多。

 

  mysql> SELECT * FROM (SELECT aid FROM feed_urls ORDER BY aid LIMIT 215000, 1) d JOIN feed_urls u ON d.aid=u.aid/G

  *************************** 1. row ***************************

  aid: 215001

  id: 2e4b1a385c8aae40b3ec2af9153805ca446f2029

  link: http://ncse.com/

  title: NCSE

  feed_url: NULL

  update_time: 2012-05-12 10:47:15

  state: queued

  http_server: NULL

  abstract: NULL

  previous_id: 819a6e3c5edc1624a9b8f171d8d3ae269843785f

  ref_count: 3

  error: NULL

  aid: 215001

  1 row in set (0.06 sec)

  mysql> EXPLAIN SELECT * FROM (SELECT aid FROM feed_urls ORDER BY aid LIMIT 215000, 1) d JOIN feed_urls u ON d.aid=u.aid/G

  *************************** 1. row ***************************

  id: 1

  select_type: PRIMARY

  table:

  type: system

  possible_keys: NULL

  key: NULL

  key_len: NULL

  ref: NULL

  rows: 1

  Extra:

  *************************** 2. row ***************************

  id: 1

  select_type: PRIMARY

  table: u

  type: const

  possible_keys: aid

  key: aid

  key_len: 4

  ref: const

  rows: 1

  Extra:

  *************************** 3. row ***************************

  id: 2

  select_type: DERIVED

  table: feed_urls

  type: index

  possible_keys: NULL

  key: aid

  key_len: 4

  ref: NULL

  rows: 211001

  Extra: Using index

  3 rows in set (0.15 sec)

 

  耗时60ms,比之前的方法快了将近10倍。如果LIMIT语句里还有WHERE a=1,应该建立一个(a,aid)的索引。

  话说,MySQL好像还是不能直接算出第21500条索引的位置呀,这种方法还是数了索引了,能算出来就直接0ms了。不过这样的效率,对于百万级的,还能应付吧。如果是千万级的或者像我之前在KS创建的一张上亿条记录的表(120G),这种方法就肯定不行了。

  经过上述优化,打开最后一页的速度已经很快了(之前需要800ms,现在则为300ms左右)。

/

  膜拜下这Burst.NET最低档次的VPS (30RMB/month)。

  root@xiaoxia-pc:~/# ping feed.readself.com -n

  PING app.readself.com (184.82.185.32) 56(84) bytes of data.

  64 bytes from 184.82.185.32: icmp_req=1 ttl=45 time=161 ms

  64 bytes from 184.82.185.32: icmp_req=2 ttl=45 time=161 ms

  64 bytes from 184.82.185.32: icmp_req=3 ttl=45 time=161 ms

  用同样的方法,优化了搜索引擎的排名算法。即排名过程中选取尽量少的值出来排序,排序后再JOIN一次获取结果的信息。

  排序过程如下:

 

  SELECT u.*, count_level(u.id) lv

  FROM(

  SELECT f.id, f.ref_count, MATCH(i.link,i.title) AGAINST (keywords) score

  FROM feed_index i

  JOIN feed_urls f ON f.id=i.id

  WHERE MATCH(i.link,i.title) AGAINST (keywords)

  ORDER BY score*0.5 + score*0.5*(ref_count/max_ref_count_in_result) DESC

  LIMIT offset,10

  ) d JOIN feed_urls u ON u.id = d.id

 

  目前处理10万记录的全文索引数据,MySQL还是可以满足的,就是不知道上百万之后,还能不能撑下去。撑不下去就依赖第三方的工具了,例如Sphinx

  3. SELECT里的函数

  给FeedDB增加了层次的显示。因为本人太懒,所以没有给数据库表增加一个记录深度的字段。所以,直接写了一个MySQL的自定义函数 count_level,用来统计通过parent_id一直找到顶层经过的路径长度(Level)。

 

  CREATE DEFINER=`feeddb_rw`@`%` FUNCTION `count_level`(fid char(40)) RETURNS int(11)

  BEGIN

  SET @levels = 0;

  SET @found = false;

  WHILE NOT @found DO

  SELECT previous_id INTO @prev_id FROM feed_urls WHERE id=fid;

  IF @prev_id is null OR @prev_id = '' THEN

  SET @found = true;

  ELSE

  SET @levels = @levels + 1;

  SET fid = @prev_id;

  END IF;

  END WHILE;

  IF @prev_id is null THEN

  RETURN null;

  END IF;

  RETURN @levels;

  END

 

  在网页显示的时候用了类似下面的SQL语句。

 

  mysql> SELECT u.*, count_level(u.id) FROM feed_urls u ORDER BY ref_count DESC LIMIT 12000,1/G

  *************************** 1. row ***************************

  id: e42f44b04dabbb9789ccb4709278e881c54c28a3

  link: http://tetellita.blogspot.com/

  title: le hamburger et le croissant

  feed_url: http://www.blogger.com/feeds/7360650/posts/default

  update_time: 2012-05-15 14:50:53

  state: ok

  http_server: GSE

  abstract: Lepekmezest un épais sirop bordeaux obtenu par réduction dumoût de raisin, une sorte de mélasse de raisin, en somme. Légèrement acidulé, il apporte du pep's aux yaourts et nappe avec bonheur les

  previous_id: 129cabd96e7099a53b78c7ddeff98658351082e9

  ref_count: 9

  error: NULL

  aid: 174262

  count_level(u.id): 8

  1 row in set (4.10 sec)

 

  好吧,悲剧了!4100ms。一定对12000个条目都算了一次count_level,然后再进行排序。所以才用上了4秒那么漫长的时间!!!

  改进方法:

  先SELECT LIMIT,再在派生的临时表里,计算count_level。

 

  mysql> SELECT u.*, count_level(u.id) FROM (

  SELECT id FROM feed_urls ORDER BY ref_count DESC LIMIT 27521,1

  ) d JOIN feed_urls u ON u.id=d.id/G

  *************************** 1. row ***************************

  id: 61df288dda131ffd6125452d20ad0648f38abafd

  link: http://mynokiamobile.org/

  title: My Nokia Mobile

  feed_url: http://mynokiamobile.org/feed/

  update_time: 2012-05-14 14:06:57

  state: ok

  http_server: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/1.0.0-fips mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635

  abstract: ArchivesSelect MonthMay 2012April 2012March 2012February 2012January 2012December 2011November 2011October 2011September 2011August 2011July 2011June 2011May 2011April 2011March 2011February 2011Janua

  previous_id: f37af92bb89c08f6d4b69e72eab05d8ab1e2aca4

  ref_count: 5

  error: NULL

  aid: 154996

  count_level(u.id): 8

  1 row in set (0.09 sec)

 

  如此,优化之后效果好很多了!但是还可以继续优化,例如建立一个字段存储Level的值应该是最好的办法了。

  初次了解MySQL一些工作机制,欢迎一起探讨!

  参考文献:

  http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/

  http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/

bitsCN.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Where can I view the records of things I have purchased on Pinduoduo? How to view the records of purchased products? Where can I view the records of things I have purchased on Pinduoduo? How to view the records of purchased products? Mar 12, 2024 pm 07:20 PM

Pinduoduo software provides a lot of good products, you can buy them anytime and anywhere, and the quality of each product is strictly controlled, every product is genuine, and there are many preferential shopping discounts, allowing everyone to shop online Simply can not stop. Enter your mobile phone number to log in online, add multiple delivery addresses and contact information online, and check the latest logistics trends at any time. Product sections of different categories are open, search and swipe up and down to purchase and place orders, and experience convenience without leaving home. With the online shopping service, you can also view all purchase records, including the goods you have purchased, and receive dozens of shopping red envelopes and coupons for free. Now the editor has provided Pinduoduo users with a detailed online way to view purchased product records. method. 1. Open your phone and click on the Pinduoduo icon.

How to view and manage Linux command history How to view and manage Linux command history Aug 01, 2023 pm 09:17 PM

How to View Command History in Linux In Linux, we use the history command to view the list of all previously executed commands. It has a very simple syntax: history Some options for pairing with the history command include: Option description -c clears the command history for the current session -w writes the command history to a file -r reloads the command history from the history file -n Limit the number of output of recent commands Simply run the history command to see a list of all previously executed commands in a Linux terminal: In addition to viewing command history, you can also manage command history and perform modifications to previously executed commands , reverse search command history or even delete history completely

How to check call history in iPhone and export it? How to check call history in iPhone and export it? Jul 05, 2023 pm 12:54 PM

Call recording in iPhone is often underestimated and is one of the most critical features of iPhone. With its simplicity, this feature is of vital importance and can provide important insights about the calls made or received on the device. Whether for work purposes or legal proceedings, the ability to access call records can prove invaluable. In simple terms, call history refers to the entries created on your iPhone whenever you make or receive a call. These logs contain key information, including the contact's name (or number if not saved as a contact), timestamp, duration, and call status (dialed, missed, or not answered). They are a concise record of your communication history. Call history includes call history strips stored on your iPhone

How to view your medication log history in the Health app on iPhone How to view your medication log history in the Health app on iPhone Nov 29, 2023 pm 08:46 PM

iPhone lets you add medications to the Health app to track and manage the medications, vitamins and supplements you take every day. You can then log medications you've taken or skipped when you receive a notification on your device. After you log your medications, you can see how often you took or skipped them to help you track your health. In this post, we will guide you to view the log history of selected medications in the Health app on iPhone. A short guide on how to view your medication log history in the Health App: Go to the Health App>Browse>Medications>Medications>Select a Medication>Options&a

How does Hibernate optimize database query performance? How does Hibernate optimize database query performance? Apr 17, 2024 pm 03:00 PM

Tips for optimizing Hibernate query performance include: using lazy loading to defer loading of collections and associated objects; using batch processing to combine update, delete, or insert operations; using second-level cache to store frequently queried objects in memory; using HQL outer connections , retrieve entities and their related entities; optimize query parameters to avoid SELECTN+1 query mode; use cursors to retrieve massive data in blocks; use indexes to improve the performance of specific queries.

C# Development Advice: Logging and Monitoring Systems C# Development Advice: Logging and Monitoring Systems Nov 22, 2023 pm 08:30 PM

C# Development Suggestions: Logging and Monitoring System Summary: In the software development process, logging and monitoring systems are crucial tools. This article will introduce the role and implementation suggestions of logging and monitoring systems in C# development. Introduction: Logging and monitoring are essential tools in large-scale software development projects. They can help us understand the running status of the program in real time and quickly discover and solve problems. This article will discuss how to use logging and monitoring systems in C# development to improve software quality and development efficiency. The role of logging system

How to log and monitor Java development projects How to log and monitor Java development projects Nov 03, 2023 am 10:09 AM

How to log and monitor Java development projects 1. Background introduction With the rapid development of the Internet, more and more companies have begun to develop Java and build various types of applications. In the development process, logging and monitoring are an important link that cannot be ignored. Through logging and monitoring, developers can discover and solve problems in time to ensure the stability and security of applications. 2. The importance of logging 1. Problem tracking: When an application error occurs, logging can help us quickly locate the problem.

How to improve the access speed of Python website through database optimization? How to improve the access speed of Python website through database optimization? Aug 07, 2023 am 11:29 AM

How to improve the access speed of Python website through database optimization? Summary When building a Python website, a database is a critical component. If the database access speed is slow, it will directly affect the performance and user experience of the website. This article will discuss some ways to optimize your database to improve the access speed of your Python website, along with some sample code. Introduction For most Python websites, the database is a key part of storing and retrieving data. If not optimized, the database can become a performance bottleneck. Book

See all articles