Mysql查询(基于某酒店2000w条数据)
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
1、僅僅是學(xué)習(xí)
前陣子手賤,下載網(wǎng)上流傳的某酒店2000w開房記錄,順手就給下載了。下載cvs格式,導(dǎo)入數(shù)據(jù)時(shí)好多失敗,隨后下載Sql-Server-2008-R2版本的記錄,由于模糊查詢非常慢,就開始改造mysql版本的(注:SQL-Server不熟而且太占內(nèi)存了,4G的基本跑起來比較費(fèi)力)。貼上SQL-Server的建表語句:
CREATE TABLE [dbo].[cdsgus]([Name] [nvarchar](2000) NULL,[CardNo] [nvarchar](2000) NULL,[Descriot] [nvarchar](2000) NULL,[CtfTp] [nvarchar](2000) NULL,[CtfId] [nvarchar](2000) NULL,[Gender] [nvarchar](2000) NULL,[Birthday] [nvarchar](2000) NULL,[Address] [nvarchar](2000) NULL,[Zip] [nvarchar](2000) NULL,[Dirty] [nvarchar](2000) NULL,[District1] [nvarchar](2000) NULL,[District2] [nvarchar](2000) NULL,[District3] [nvarchar](2000) NULL,[District4] [nvarchar](2000) NULL,[District5] [nvarchar](2000) NULL,[District6] [nvarchar](2000) NULL,[FirstNm] [nvarchar](2000) NULL,[LastNm] [nvarchar](2000) NULL,[Duty] [nvarchar](2000) NULL,[Mobile] [nvarchar](2000) NULL,[Tel] [nvarchar](2000) NULL,[Fax] [nvarchar](2000) NULL,[EMail] [nvarchar](2000) NULL,[Nation] [nvarchar](2000) NULL,[Taste] [nvarchar](2000) NULL,[Education] [nvarchar](2000) NULL,[Company] [nvarchar](2000) NULL,[CTel] [nvarchar](2000) NULL,[CAddress] [nvarchar](2000) NULL,[CZip] [nvarchar](2000) NULL,[Family] [nvarchar](2000) NULL,[Version] [nvarchar](2000) NULL,[id] [int] IDENTITY(1,1) NOT NULL,CONSTRAINT [PK_cdsgus] PRIMARY KEY CLUSTERED ([id] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
從建表語句看,這表建得實(shí)在是不太好!不管,先看看數(shù)據(jù)有多少:
select COUNT(*) FROM [shifenzheng].[dbo].[cdsgus]; # 查詢非常慢的(5分鐘左右)
2、開始MySql之旅?
開始導(dǎo)入數(shù)據(jù)(開始mysql建表語句也和上面一樣),然后幾經(jīng)折騰,最終確定表結(jié)構(gòu)如下(內(nèi)存不夠,放棄ENGINE=MEMORY):mysql> show create table customer; +--------------------------+ | Table | Create Table +--------------------------+ | customer | CREATE TABLE `customer` (`Name` varchar(80) NOT NULL,`CardNo` varchar(10) DEFAULT NULL,`Descriot` varchar(100) DEFAULT NULL,`CtfTp` varchar(4) DEFAULT NULL,`CtfId` varchar(40) DEFAULT NULL,`Gender` varchar(8) DEFAULT NULL,`Birthday` int(9) DEFAULT NULL,`Address` varchar(100) DEFAULT NULL,`Zip` int(10) DEFAULT NULL,`Dirty` varchar(20) DEFAULT NULL,`District1` varchar(6) DEFAULT NULL,`District2` varchar(4) DEFAULT NULL,`District3` varchar(6) DEFAULT NULL,`District4` varchar(6) DEFAULT NULL,`District5` varchar(8) DEFAULT NULL,`District6` varchar(20) DEFAULT NULL,`FirstNm` varchar(50) DEFAULT NULL,`LastNm` varchar(20) DEFAULT NULL,`Duty` varchar(20) DEFAULT NULL,`Mobile` varchar(40) DEFAULT NULL,`Tel` varchar(40) DEFAULT NULL,`Fax` varchar(40) DEFAULT NULL,`EMail` varchar(60) DEFAULT NULL,`Nation` varchar(25) DEFAULT NULL,`Taste` varchar(100) DEFAULT NULL,`Education` varchar(20) DEFAULT NULL,`Company` varchar(80) DEFAULT NULL,`CTel` varchar(20) DEFAULT NULL,`CAddress` varchar(60) DEFAULT NULL,`CZip` int(8) DEFAULT NULL,`Family` int(10) DEFAULT NULL,`Version` datetime DEFAULT NULL,`id` int(11) NOT NULL,PRIMARY KEY (`id`),KEY `index_Name` (`Name`) USING BTREE,KEY `index_CtfId` (`CtfId`) USING BTREE ) ENGINE=MyISAM DEFAULT CHARSET=utf8 | +--------------------------+mysql> show create table test; +--------------------------+ | Table | Create Table +--------------------------+ | test | CREATE TABLE `test` (`Name` varchar(80) NOT NULL,`CardNo` varchar(10) DEFAULT NULL,`Descriot` varchar(100) DEFAULT NULL,`CtfTp` varchar(4) DEFAULT NULL,`CtfId` varchar(40) DEFAULT NULL,`Gender` varchar(8) DEFAULT NULL,`Birthday` int(9) DEFAULT NULL,`Address` varchar(100) DEFAULT NULL,`Zip` int(10) DEFAULT NULL,`Dirty` varchar(20) DEFAULT NULL,`District1` varchar(6) DEFAULT NULL,`District2` varchar(4) DEFAULT NULL,`District3` varchar(6) DEFAULT NULL,`District4` varchar(6) DEFAULT NULL,`District5` varchar(8) DEFAULT NULL,`District6` varchar(20) DEFAULT NULL,`FirstNm` varchar(50) DEFAULT NULL,`LastNm` varchar(20) DEFAULT NULL,`Duty` varchar(20) DEFAULT NULL,`Mobile` varchar(40) DEFAULT NULL,`Tel` varchar(40) DEFAULT NULL,`Fax` varchar(40) DEFAULT NULL,`EMail` varchar(60) DEFAULT NULL,`Nation` varchar(25) DEFAULT NULL,`Taste` varchar(100) DEFAULT NULL,`Education` varchar(20) DEFAULT NULL,`Company` varchar(80) DEFAULT NULL,`CTel` varchar(20) DEFAULT NULL,`CAddress` varchar(60) DEFAULT NULL,`CZip` int(8) DEFAULT NULL,`Family` int(10) DEFAULT NULL,`Version` datetime DEFAULT NULL,`id` int(11) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 | +--------------------------+
表customer,test結(jié)構(gòu)式一樣的,數(shù)據(jù)也是一樣的,只是customer多了兩個(gè)索引:
KEY `index_Name` (`Name`) USING BTREE,KEY `index_CtfId` (`CtfId`) USING BTREE終端編碼統(tǒng)一設(shè)置成utf8:
mysql> show variables like '%char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+
先看看表空間的大小:
mysql> select table_name, data_length/(1024 * 1024), index_length/(1024 * 1024) from tables where table_schema='hotel'; +------------+---------------------------+----------------------------+ | table_name | data_length/(1024 * 1024) | index_length/(1024 * 1024) | +------------+---------------------------+----------------------------+ | customer | 2713.3337 | 566.7627 | | test | 2713.3337 | 196.2305 | +------------+---------------------------+----------------------------+ 2 rows in set (0.00 sec) 多了兩列的索引就多了370M左右。3、MySql的測(cè)試數(shù)據(jù):
| 條數(shù)\時(shí)間 | TABLE `test` | TABLE `customer` |
| ① | | |
| count(*) ... where name like '徐%' | 369670 (1 min 2.63 sec) | 369670 (0.45 sec) |
| count(*) ... where name like 'xu%' ? ? ? ? ?? | 1834 (1 min 2.32 sec) | ?1834 (0.45 sec) |
| name ... where name like '徐%' ?? | 369670 (1 min 2.91 sec) | 369670 (0.30 sec) |
| name ... where name like 'xu%' | 1834 (1 min 3.27 sec) ? | 1834 (0.15 sec) |
| name ... where binary?name like 'xu%' | 605 (1 min 2.89 sec) | ?605 (7.62 sec) |
| ② | | |
| count(*) ... where name like '%徐' | 912(1 min 1.89 sec) | 912(7.45 sec) |
| count(*) ... where name like '%xu'? | 326(1 min 1.71 sec) | ?326(7.25 sec) |
| name ... where name like '%徐' | 912 (1 min 3.19 sec) | ?912 (7.42 sec) |
| name ... where name like '%xu'? | ?326 (1 min 3.69 sec) ? | 326 (7.48 sec) |
| name ... where binary?name like '%xu' | 117 (1 min 7.49 sec)? | ?117 (6.76 sec) |
| ③ | | |
| count(*) ... where name like '%徐%' | 373621(1 min 2.98 sec) | ?373621(8.08 sec) |
| count(*) ... where name like '%xu%' | ?3347(1 min 3.26 sec) | 3347(7.98 sec) ? |
| name ... where name like '%徐%' | 373621 (1 min 3.02 sec) | 373621 (7.49 sec) |
| name ... where name like '%xu%' | ?3347 (1 min 3.55 sec) | 3347 (7.29 sec) |
| name ... where binary?name like '%xu%' | 1059 (1 min 2.93 sec)? | 1059 (6.94 sec) |
| ④ | | |
| name,ctfid,id ... where name like '徐%' ? | ?369670 (1 min 1.48 sec)? | 369670 (大于40min) |
| name,ctfid,id ... where name like 'xu%'? | ?1834 (1 min 1.40 sec) ? | ?1834 (17.77, 0.02 sec) |
| name,ctfid,id ... where name binary like 'xu%' | 605 (1 min 4.45 sec) ? | 605 (1min 12.59 sec) |
| ⑤ | | |
| name,ctfid,id ... where name like '%徐%'? | 373621 (1 min 2.59 sec) | ?373621 (1 min 2.18 sec) |
| name,ctfid,id ... where name like '%xu%' ? | 3347 (1 min 5.52 sec) | ?3347 (1min 1.77 sec) |
| name,ctfid,id ... where binary?name like '%xu%'? | 1059 (1 min 2.83 sec) | ?1059 (1min 0.38 sec) |
| ⑥ | | |
| name ... where name = '徐'? | 120 (1 min 2.70 sec) | 120 (0.16 sec) |
| name ... where name = 'xu' | ?38 (1 min 8.17 sec)? | 38 (0.01 sec) |
| ⑦ | | |
| name,ctfid,id ... where name = '徐' | 120 (1 min 11.80 sec)? | 120 (0.60 sec) |
| name,ctfid,id ... where name = 'xu'? | 38 (1 min 3.43 sec) | 38 (0.58 sec) |
| ⑧ | | |
| name,ctfid,id ... where name like '%徐%' limit 1000? | 1000 (0.05 sec) | 1000 (0.06 sec) |
| name,ctfid,id ... where name like '%徐%' limit 10000? | 10000 (0.40 sec) | 10000 (0.39 sec) |
| name,ctfid,id ... where name like '%xu%' limit 1000 | 1000 (18.91 sec) | 1000 (19.28 sec) |
| name,ctfid,id ... where name like '%xu%' limit 10000 | ?10000 (1 min 1.74 sec)? | 10000 (59.71 sec) |
| ⑨ | | |
| name,ctfid,id ... where name like '%徐%' limit 1000, 1000? | 1000 (0.31 sec) | 1000 (0.31 sec) |
| name,ctfid,id ... where name like '%徐%' limit 10000, 1000? | 1000 (1.48, 0.41 sec) | 1000 (1.52, 0.46 sec) |
| name,ctfid,id ... where name like '%徐%' limit 100000, 1000? | 1000 (17.18, 17.01 sec) | 1000 (14.01, 13.61 sec) |
| name,ctfid,id ... where name like '%xu%' limit 1000,1000 | 1000?(44.71 sec) | 1000?(41.81 sec) |
| name,ctfid,id ... where name like '%xu%' limit 2000,1000 | 1000?(48.02 sec) | 1000?(49.56 sec) |
注:有索引的時(shí)候,模糊查詢單列數(shù)據(jù)占有很大的優(yōu)勢(shì),等于查詢也是。對(duì)比①②發(fā)現(xiàn),模糊查詢還是開始字符不模糊很有優(yōu)勢(shì)的(基本可以了解索引的分組規(guī)則)。第④條,說明索引也是有問題的,大概46分鐘的時(shí)間(可能是bug),第④的第二條說明索引查詢過的數(shù)據(jù)會(huì)緩存起來,索引第二次查詢明顯很快。對(duì)比binary(區(qū)分大小寫),明顯更加耗時(shí)。第⑨條,說明越往后的數(shù)據(jù),limit查詢起來越費(fèi)時(shí)。
4、待解決的問題
limit關(guān)鍵字在數(shù)據(jù)量很多的性能瓶頸,其實(shí)就如這篇文章所說的:http://www.cnblogs.com/fjytzh/archive/2010/04/02/1702886.html,offset偏移比較大時(shí),可以采用嵌套查詢的方式來提高效率,但是目前我需要滿足模糊查詢的需要,這個(gè)方案有問題(確實(shí)測(cè)試了一下,不可行,比直接limit還要慢)。
試試http://grb12508.blog.163.com/blog/static/273784582009102448061/復(fù)合索引的方法(綜上:如果對(duì)于有where 條件,又想走索引用limit的,必須設(shè)計(jì)一個(gè)索引,將where 放第一位,limit用到的主鍵放第2位,而且只能select 主鍵!),主要想通過name來查詢id,故以name, id建復(fù)合索引(測(cè)試結(jié)果還可以)。
-- 添加復(fù)合索引alter table test add index (name, id); -- 查詢的SQL語句(注意:這里如果用 id in (...)會(huì)很慢! http://codingstandards.iteye.com/blog/1344833 )select name, ctfid, id from test t inner join (select id as i_id from test where name like '徐%' limit 20000, 2000) as i on t.id=i.i_id;
第一次查詢比較慢,重復(fù)查詢一下就很快(應(yīng)該有緩存)。
5、最終建表語句
CREATE TABLE `customer` (`Name` varchar(80) NOT NULL,`CardNo` varchar(10) DEFAULT NULL,`Descriot` varchar(100) DEFAULT NULL,`CtfTp` varchar(4) DEFAULT NULL,`CtfId` varchar(40) DEFAULT NULL,`Gender` varchar(8) DEFAULT NULL,`Birthday` int(9) DEFAULT NULL,`Address` varchar(100) DEFAULT NULL,`Zip` int(10) DEFAULT NULL,`Dirty` varchar(20) DEFAULT NULL,`District1` varchar(6) DEFAULT NULL,`District2` varchar(4) DEFAULT NULL,`District3` varchar(6) DEFAULT NULL,`District4` varchar(6) DEFAULT NULL,`District5` varchar(8) DEFAULT NULL,`District6` varchar(20) DEFAULT NULL,`FirstNm` varchar(50) DEFAULT NULL,`LastNm` varchar(20) DEFAULT NULL,`Duty` varchar(20) DEFAULT NULL,`Mobile` varchar(40) DEFAULT NULL,`Tel` varchar(40) DEFAULT NULL,`Fax` varchar(40) DEFAULT NULL,`EMail` varchar(60) DEFAULT NULL,`Nation` varchar(25) DEFAULT NULL,`Taste` varchar(100) DEFAULT NULL,`Education` varchar(20) DEFAULT NULL,`Company` varchar(80) DEFAULT NULL,`CTel` varchar(20) DEFAULT NULL,`CAddress` varchar(60) DEFAULT NULL,`CZip` int(8) DEFAULT NULL,`Family` int(10) DEFAULT NULL,`Version` datetime DEFAULT NULL,`id` int(11) NOT NULL,PRIMARY KEY (`id`),KEY `index_Name_Id` (`Name`, `id`) USING BTREE,KEY `index_CtfId_Id` (`CtfId`, `id`) USING BTREE ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
轉(zhuǎn)載于:https://my.oschina.net/twinkling/blog/180619
總結(jié)
以上是生活随笔為你收集整理的Mysql查询(基于某酒店2000w条数据)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Rethinking the small
- 下一篇: 问题反馈模板_使用此模板可获得更好,更有