查询
SELECT id FROM `user_tmp`
WHERE `code` = '9s5xs1sy'
AND `go` NOT REGEXP 'http://www.xxxx.example.com/aflam/|http://xx.example.com|http://www.xxxxx..example.com/aflam/|http://www.xxxxxx.example.com/v/|http://www.xxxxxx.example.com/vb/'
AND check='done'
AND `dataip` <1319992460
ORDER BY id DESC
LIMIT 50
MySQL返回:
Showing rows 0 - 29 ( 50 total, Query took 21.3102 sec) [id: 2622270 - 2602288]
查询耗时21.3102秒
如果我删除
AND dataip
&lt; 1319992460
MySQL返回
Showing rows 0 - 29 ( 50 total, Query took 0.0859 sec) [id: 3637556 - 3627005]
查询耗时0.0859秒
如果没有数据,MySQL返回
MySQL returned an empty result set (i.e. zero rows). ( Query took 21.7332 sec )
查询耗时21.7332秒
解释计划:
SQL query: Explain SELECT * FROM `user_tmp` WHERE `code` = '93mhco3s5y' AND `too` NOT REGEXP 'http://www.10neen.com/aflam/|http://3ltool.com|http://www.10neen.com/aflam/|http://www.10neen.com/v/|http://www.m1-w3d.com/vb/' and checkopen='2010' and `dataip` <1319992460 ORDER BY id DESC LIMIT 50;
Rows: 1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE user_tmp index NULL PRIMARY 4 NULL 50 Using where
使用的数据库示例
CREATE TABLE IF NOT NOT EXISTS
user_tmp
(id
int(9)NOT NULL AUTO_INCREMENT,ip
text NOT NULL,dataip
bigint(20)NOT NULL,ref
text NOT NULL,click
int(20)NOT NULL,code
text NOT NULL,too
text NOT NULL,name
text NOT NULL,checkopen
text NOT NULL,contry
text NOT NULL,vOperation
text NOT NULL,vBrowser
text NOT NULL,iconOperation
text NOT NULL,
iconBrowser
文本NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4653425 ;
-
user_tmp
INSERT INTO `user_tmp` (`id`, `ip`, `dataip`, `ref`, `click`, `code`, `too`, `name`, `checkopen`, `contry`, `vOperation`, `vBrowser`, `iconOperation`, `iconBrowser`) VALUES
(1, '54.125.78.84', 1319506641, 'http://xxxx.example.com/vb/showthread.php%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D8%BA%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%A8%D9%88%D9%85-giovanni-marradi-lovers-rendezvous-3cd-1999-a-155712.html', 0, '4mxxxxx5', 'http://www.xxx.example.com/aflam/', 'xxxxe', '2010', 'US', 'Linux', 'Chrome 12.0.742 ', 'linux.png', 'chrome.png');
我想要正确的方法来进行查询和优化数据库
答案 0 :(得分:1)
除了主键之外,您没有任何索引。您需要在WHERE语句中使用的字段上创建索引。如果您只需索引1个字段或多个字段的组合取决于您将针对该表运行的其他SELECT。
请记住,REGEXP
根本不能使用索引,LIKE
只有在不以通配符开头时才能使用索引(因此LIKE 'a%'
可以使用索引,但LIKE '%a'
不能),大于/小于(&lt;&gt;)通常也不使用索引。
因此,您将留下code
和check
字段。我想很多行对check
都有相同的值,所以我会用code
字段开始索引。多字段索引只能按照定义它们的顺序使用...
想象一下为字段code, check
创建的索引。此索引可以在您的查询中使用(WHERE子句包含两个字段),也可以在仅包含code
字段的查询中使用,但不能在仅包含check
字段的查询中使用。
对ORDER BY id
重要吗?如果没有,请将其保留,它将阻止排序通过,您的查询将更快完成。
答案 1 :(得分:1)
我假设你使用的是mysql&lt; = 5.1
上述答案分为两个基本类别: 1.您使用的是错误的列类型 你需要索引
我会处理每一项因为两者都与表现有关,这最终是我提出的问题所在:
列类型 dataip问题的bigint / int或int / char之间的区别与您的问题基本无关。根本问题更多地与指数战略有关。但是,当从整体上考虑性能时,您使用MyISAM作为此表的引擎这一事实会让我问您是否确实需要“文本”列类型。如果你有短的(少于255个说)字符列,那么使它们成为固定长度的列很可能会提高性能。请记住,如果任何一列具有可变长度(varchar,text等),那么这不值得更改任何一列。
垂直分区
这里要记住的事实是,即使您只是从磁盘IO和内存的角度请求id
列,您也可以获得整行。由于这么多行都是文本,这可能意味着大量的数据。任何未用于查找用户或不经常访问的行都可以移动到另一个表中,其中外键上放有唯一键,保持关系1:1。
指数策略
如上所述,问题很可能只是索引。您当前情况是由添加“AND dataip
&lt; 1319992460”条件引起的原因是它强制进行全表扫描。
如上所述,将where子句中的所有列放在单个复合索引中会有所帮助。只要所有列都出现在where子句中,索引中列的顺序就无论如何。
但是,订单对于其他查询可能很重要。一个简单的例子是由(colA,colB)构成的索引。带有“where colA ='foo'”的查询将使用此索引。但是带有“where colB ='bar'”的查询不会,因为colB不是索引定义中最左边的列。因此,如果您有其他查询在某些组合中使用这些列,则值得最小化在表上创建的索引数。这是b / c每个索引都会增加写入的成本并使用磁盘空间。写入是必要磁盘活动的昂贵b / c。不要让它们更贵。
答案 2 :(得分:0)
你需要像这样添加索引:
ALTER TABLE `user_tmp` ADD INDEX(`dataip`);
如果您的列'dataip'仅包含唯一值,则可以添加如下所示的唯一键:
ALTER TABLE `user_tmp` ADD UNIQUE(`dataip`);
请记住,在大表上添加索引可能需要很长时间,因此请不要在生产服务器上进行测试。
答案 3 :(得分:0)
您需要按照在where子句中使用的顺序在字段上创建索引。否则不使用索引。 where子句的索引字段。
答案 4 :(得分:0)
dataip真的需要一个bigint吗?根据mysql的签名范围是-9223372036854775808到9223372036854775807(这是一个64位的数字)。
您需要为作业选择正确的列类型,并添加正确的索引类型。否则这些查询将永远存在。