众所周知,在MySQL中,如果直接 ORDER BY RAND() 的话,效率非常差,因为会多次执行。事实上,如果等值查询也是用 RAND() 的话也如此,我们先来看看下面这几个SQL的不同执行计划和执行耗时。首先,看下建表DDL,这是一个没有显式自增主键的InnoDB表:
[yejr@imysql]> show create table t_innodb_random/G*************************** 1. row ***************************Table: t_innodb_randomCreate Table: CREATE TABLE `t_innodb_random` (`id` int(10) unsigned NOT NULL,`user` varchar(64) NOT NULL DEFAULT '',KEY `idx_id` (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1
往这个表里灌入一些测试数据,至少10万以上, id 字段也是乱序的。
[yejr@imysql]> select count(*) from t_innodb_random/G*************************** 1. row ***************************count(*): 393216
1、常量等值检索:
[yejr@imysql]> explain select id from t_innodb_random where id = 13412/G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_innodb_randomtype: refpossible_keys: idx_idkey: idx_idkey_len: 4<strong>ref: constrows: 1Extra: Using index</strong>[yejr@imysql]> select id from t_innodb_random where id = 13412;1 row in set (0.00 sec)
可以看到执行计划很不错,是常量等值查询,速度非常快。
2、使用RAND()函数乘以常量,求得随机数后检索:
[yejr@imysql]> explain select id from t_innodb_random where id = round(rand()*13241324)/G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_innodb_randomtype: indexpossible_keys: NULLkey: idx_idkey_len: 4<strong>ref: NULLrows: 393345Extra: Using where; Using index</strong>[yejr@imysql]> select id from t_innodb_random where id = round(rand()*13241324)/GEmpty set (0.26 sec)
可以看到执行计划很糟糕,虽然是只扫描索引,但是做了全索引扫描,效率非常差。因为WHERE条件中包含了RAND(),使得MySQL把它当做变量来处理,无法用常量等值的方式查询,效率很低。
我们把常量改成取t_innodb_random表的最大id值,再乘以RAND()求得随机数后检索看看什么情况:
[yejr@imysql]> explain select id from t_innodb_random where id = round(rand()*(select max(id) from t_innodb_random))/G*************************** 1. row ***************************id: 1select_type: PRIMARYtable: t_innodb_randomtype: indexpossible_keys: NULLkey: idx_idkey_len: 4<strong>ref: NULLrows: 393345Extra: Using where; Using index</strong>*************************** 2. row ***************************id: 2select_type: SUBQUERYtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Select tables optimized away[yejr@imysql]> select id from t_innodb_random where id = round(rand()*(select max(id) from t_innodb_random))/GEmpty set (0.27 sec)
可以看到,执行计划依然是全索引扫描,执行耗时也基本相当。
3、改造成普通子查询模式 ,这里有两次子查询
<strong>[yejr@imysql]> explain select id from t_innodb_random where id = (select round(rand()*(select max(id) from t_innodb_random)) as nid)/G*************************** 1. row ***************************id: 1select_type: PRIMARYtable: t_innodb_randomtype: indexpossible_keys: NULLkey: idx_idkey_len: 4ref: NULLrows: 393345Extra: Using where; Using index*************************** 2. row ***************************id: 3select_type: SUBQUERYtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Select tables optimized away[yejr@imysql]> select id from t_innodb_random where id = (select round(rand()*(select max(id) from t_innodb_random)) as nid)/GEmpty set (0.27 sec)</strong>
可以看到,执行计划也不好,执行耗时较慢。
4、改造成JOIN关联查询,不过最大值还是用常量表示
[yejr@imysql]> explain select id from t_innodb_random t1 join (select round(rand()*13241324) as id2) as t2 where t1.id = t2.id2/G*************************** 1. row ***************************id: 1select_type: PRIMARYtable: <derived2>type: systempossible_keys: NULLkey: NULLkey_len: NULL<strong>ref: NULLrows: 1Extra:</strong>*************************** 2. row ***************************id: 1select_type: PRIMARYtable: t1type: refpossible_keys: idx_idkey: idx_idkey_len: 4<strong>ref: constrows: 1Extra: Using where; Using index</strong>*************************** 3. row ***************************id: 2select_type: DERIVEDtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: No tables used[yejr@imysql]> select id from t_innodb_random t1 join (select round(rand()*13241324) as id2) as t2 where t1.id = t2.id2/GEmpty set (0.00 sec)</derived2>
这时候执行计划就非常完美了,和最开始的常量等值查询是一样的了,执行耗时也非常之快。这种方法虽然很好,但是有可能查询不到记录,改造范围查找,但结果LIMIT 1就可以了:
[yejr@imysql]> explain select id from t_innodb_random where id > (select round(rand()*(select max(id) from t_innodb_random)) as nid) limit 1/G*************************** 1. row ***************************id: 1select_type: PRIMARYtable: t_innodb_randomtype: indexpossible_keys: NULLkey: idx_idkey_len: 4<strong>ref: NULLrows: 393345Extra: Using where; Using index</strong>*************************** 2. row ***************************id: 3select_type: SUBQUERYtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Select tables optimized away[yejr@imysql]> select id from t_innodb_random where id > (select round(rand()*(select max(id) from t_innodb_random)) as nid) limit 1/G*************************** 1. row ***************************id: 13011 row in set (0.00 sec)
可以看到,虽然执行计划也是全索引扫描,但是因为有了LIMIT 1,只需要找到一条记录,即可终止扫描,所以效率还是很快的。
小结:从数据库中随机取一条记录时,可以把RAND()生成随机数放在JOIN子查询中以提高效率。
5、再来看看用ORDRR BY RAND()方式一次取得多个随机值的方式:
[yejr@imysql]> explain select id from t_innodb_random order by rand() limit 1000/G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t_innodb_randomtype: indexpossible_keys: NULLkey: idx_idkey_len: 4<strong>ref: NULLrows: 393345Extra: Using index; Using temporary; Using filesort</strong>[yejr@imysql]> select id from t_innodb_random order by rand() limit 1000;1000 rows in set (0.41 sec)
全索引扫描,生成排序临时表,太差太慢了。
6、把随机数放在子查询里看看:
[yejr@imysql]> explain select id from t_innodb_random where id > (select rand() * (select max(id) from t_innodb_random) as nid) limit 1000/G*************************** 1. row ***************************id: 1select_type: PRIMARYtable: t_innodb_randomtype: indexpossible_keys: NULLkey: idx_idkey_len: 4<strong>ref: NULLrows: 393345Extra: Using where; Using index</strong>*************************** 2. row ***************************id: 3select_type: SUBQUERYtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Select tables optimized away[yejr@imysql]> select id from t_innodb_random where id > (select rand() * (select max(id) from t_innodb_random) as nid) limit 1000/G1000 rows in set (0.04 sec)
嗯,提速了不少,这个看起来还不赖:)
7、仿照上面的方法,改成JOIN和随机数子查询关联
[yejr@imysql]> explain select id from t_innodb_random t1 join (select rand() * (select max(id) from t_innodb_random) as nid) t2 on t1.id > t2.nid limit 1000/G*************************** 1. row ***************************id: 1select_type: PRIMARYtable: <derived2>type: systempossible_keys: NULLkey: NULLkey_len: NULL<strong>ref: NULLrows: 1Extra:</strong>*************************** 2. row ***************************id: 1select_type: PRIMARYtable: t1type: rangepossible_keys: idx_idkey: idx_idkey_len: 4<strong>ref: NULLrows: 196672Extra: Using where; Using index</strong>*************************** 3. row ***************************id: 2select_type: DERIVEDtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: No tables used*************************** 4. row ***************************id: 3select_type: SUBQUERYtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Select tables optimized away[yejr@imysql]> select id from t_innodb_random t1 join (select rand() * (select max(id) from t_innodb_random) as nid) t2 on t1.id > t2.nid limit 1000/G1000 rows in set (0.00 sec)</derived2>
可以看到,全索引检索,发现符合记录的条件后,直接取得1000行,这个方法是最快的。
综上,想从MySQL数据库中随机取一条或者N条记录时,最好把RAND()生成随机数放在JOIN子查询中以提高效率。上面说了那么多的废话,最后简单说下,就是把下面这个SQL:
SELECT id FROM table ORDER BY RAND() LIMIT n;
改造成下面这个:
SELECT id FROM table t1, JOIN (SELECT RAND() * (SELECT MAX(id) FROM table) AS nid) t2 ON t1.id > t2.nid LIMIT n;
就可以享受在SQL中直接取得随机数了,不用再在程序中构造一串随机数去检索了。

innodbbufferpool은 데이터와 인덱싱 페이지를 캐싱하여 디스크 I/O를 줄여 데이터베이스 성능을 향상시킵니다. 작업 원칙에는 다음이 포함됩니다. 1. 데이터 읽기 : BufferPool의 데이터 읽기; 2. 데이터 작성 : 데이터 수정 후 BufferPool에 쓰고 정기적으로 디스크로 새로 고치십시오. 3. 캐시 관리 : LRU 알고리즘을 사용하여 캐시 페이지를 관리합니다. 4. 읽기 메커니즘 : 인접한 데이터 페이지를 미리로드합니다. Bufferpool을 크기를 조정하고 여러 인스턴스를 사용하여 데이터베이스 성능을 최적화 할 수 있습니다.

다른 프로그래밍 언어와 비교할 때 MySQL은 주로 데이터를 저장하고 관리하는 데 사용되는 반면 Python, Java 및 C와 같은 다른 언어는 논리적 처리 및 응용 프로그램 개발에 사용됩니다. MySQL은 데이터 관리 요구에 적합한 고성능, 확장 성 및 크로스 플랫폼 지원으로 유명하며 다른 언어는 데이터 분석, 엔터프라이즈 애플리케이션 및 시스템 프로그래밍과 같은 해당 분야에서 이점이 있습니다.

MySQL은 데이터 저장, 관리 및 분석에 적합한 강력한 오픈 소스 데이터베이스 관리 시스템이기 때문에 학습 할 가치가 있습니다. 1) MySQL은 SQL을 사용하여 데이터를 작동하고 구조화 된 데이터 관리에 적합한 관계형 데이터베이스입니다. 2) SQL 언어는 MySQL과 상호 작용하는 열쇠이며 CRUD 작업을 지원합니다. 3) MySQL의 작동 원리에는 클라이언트/서버 아키텍처, 스토리지 엔진 및 쿼리 최적화가 포함됩니다. 4) 기본 사용에는 데이터베이스 및 테이블 작성이 포함되며 고급 사용량은 Join을 사용하여 테이블을 결합하는 것과 관련이 있습니다. 5) 일반적인 오류에는 구문 오류 및 권한 문제가 포함되며 디버깅 기술에는 구문 확인 및 설명 명령 사용이 포함됩니다. 6) 성능 최적화에는 인덱스 사용, SQL 문의 최적화 및 데이터베이스의 정기 유지 보수가 포함됩니다.

MySQL은 초보자가 데이터베이스 기술을 배우는 데 적합합니다. 1. MySQL 서버 및 클라이언트 도구를 설치하십시오. 2. SELECT와 같은 기본 SQL 쿼리를 이해하십시오. 3. 마스터 데이터 작업 : 데이터를 만들고, 삽입, 업데이트 및 삭제합니다. 4. 고급 기술 배우기 : 하위 쿼리 및 창 함수. 5. 디버깅 및 최적화 : 구문 확인, 인덱스 사용, 선택*을 피하고 제한을 사용하십시오.

MySQL은 테이블 구조 및 SQL 쿼리를 통해 구조화 된 데이터를 효율적으로 관리하고 외래 키를 통해 테이블 간 관계를 구현합니다. 1. 테이블을 만들 때 데이터 형식을 정의하고 입력하십시오. 2. 외래 키를 사용하여 테이블 간의 관계를 설정하십시오. 3. 인덱싱 및 쿼리 최적화를 통해 성능을 향상시킵니다. 4. 데이터 보안 및 성능 최적화를 보장하기 위해 데이터베이스를 정기적으로 백업 및 모니터링합니다.

MySQL은 웹 개발에 널리 사용되는 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 주요 기능에는 다음이 포함됩니다. 1. 다른 시나리오에 적합한 InnoDB 및 MyISAM과 같은 여러 스토리지 엔진을 지원합니다. 2.로드 밸런싱 및 데이터 백업을 용이하게하기 위해 마스터 슬레이브 복제 기능을 제공합니다. 3. 쿼리 최적화 및 색인 사용을 통해 쿼리 효율성을 향상시킵니다.

SQL은 MySQL 데이터베이스와 상호 작용하여 데이터 첨가, 삭제, 수정, 검사 및 데이터베이스 설계를 실현하는 데 사용됩니다. 1) SQL은 Select, Insert, Update, Delete 문을 통해 데이터 작업을 수행합니다. 2) 데이터베이스 설계 및 관리에 대한 생성, 변경, 삭제 문을 사용하십시오. 3) 복잡한 쿼리 및 데이터 분석은 SQL을 통해 구현되어 비즈니스 의사 결정 효율성을 향상시킵니다.

MySQL의 기본 작업에는 데이터베이스, 테이블 작성 및 SQL을 사용하여 데이터에서 CRUD 작업을 수행하는 것이 포함됩니다. 1. 데이터베이스 생성 : createAbasemy_first_db; 2. 테이블 만들기 : CreateTableBooks (idintauto_incrementprimarykey, titlevarchar (100) notnull, authorvarchar (100) notnull, published_yearint); 3. 데이터 삽입 : InsertIntobooks (Title, Author, Published_year) VA


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

Dreamweaver Mac版
시각적 웹 개발 도구

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기
