Redian新闻
>
mysql index优化求助 (转载)
avatar
mysql index优化求助 (转载)# Database - 数据库
v*s
1
【 以下文字转载自 Programming 讨论区 】
发信人: vicfcs (ML+CV), 信区: Programming
标 题: mysql index优化求助
发信站: BBS 未名空间站 (Thu Feb 3 10:53:18 2011, 美东)
目前的一个project需要在mysql里面查询 两个node之间的value,
table columns:
LOOKUPTABLE (INT id, VARCHAR node1, VARCHAR node2, INT value)
问题是这个table有 10 millions rows, 一次select query时间大概是 3 sec:
select value from LOOKUPTABLE where node1 = 'a' and node2 = 'b';
尝试用index来优化query,但是不知道最优的index应该是哪种?谢谢!包子有赏!
avatar
B*g
2
??
http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.

【在 v****s 的大作中提到】
: 【 以下文字转载自 Programming 讨论区 】
: 发信人: vicfcs (ML+CV), 信区: Programming
: 标 题: mysql index优化求助
: 发信站: BBS 未名空间站 (Thu Feb 3 10:53:18 2011, 美东)
: 目前的一个project需要在mysql里面查询 两个node之间的value,
: table columns:
: LOOKUPTABLE (INT id, VARCHAR node1, VARCHAR node2, INT value)
: 问题是这个table有 10 millions rows, 一次select query时间大概是 3 sec:
: select value from LOOKUPTABLE where node1 = 'a' and node2 = 'b';
: 尝试用index来优化query,但是不知道最优的index应该是哪种?谢谢!包子有赏!

avatar
B*g
4
The best way to confirm one is better than the other is try both, hehe.
maybe the table already has index on (n1,n2)

【在 a9 的大作中提到】
: 0.8秒不算很慢了吧?如果node1有索引,而且按这个条件检索出来的很少,不见得两个
: column的索引会比这个快很多。

avatar
v*s
5
sorry, i just did 1000 runs today and the average is about 3 sec....

【在 a9 的大作中提到】
: 0.8秒不算很慢了吧?如果node1有索引,而且按这个条件检索出来的很少,不见得两个
: column的索引会比这个快很多。

avatar
v*s
6
除了index,还有什么可以优化的么?
我试过了btree, hash,都没有显著提高

【在 B*****g 的大作中提到】
: The best way to confirm one is better than the other is try both, hehe.
: maybe the table already has index on (n1,n2)

avatar
a9
7
你现在有啥索引啊?

两个
the selfish and the tyranny of evil men. Blessed is he who in the name of
charity and goodwill shepherds the weak through the valley of darkness, for
he is truly his brother’s keepe:

【在 v****s 的大作中提到】
: sorry, i just did 1000 runs today and the average is about 3 sec....
avatar
B*g
8
先把table结构贴出来,index, partition...

the selfish and the tyranny of evil men. Blessed is he who in the name of
charity and goodwill shepherds the weak through the valley of darkness, for
he is truly his brother’s keepe:

【在 v****s 的大作中提到】
: 除了index,还有什么可以优化的么?
: 我试过了btree, hash,都没有显著提高

avatar
v*s
9
谢谢各位!这是create table statement, 请帮忙看看如何提高select 的速度。
我只用这个语句:
select * from shortest where ((p1=x and p2=y) or (p1=y and p2=y))
delimiter $$
CREATE TABLE `shortest` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`p1` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
'',
`p2` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
'',
`dist` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL
DEFAULT '',
PRIMARY KEY (`id`),
KEY `p1p2` (`p1`,`p2`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4323060 DEFAULT CHARSET=latin1$$
avatar
a9
10
用select * from shortest where p2=y and (p1=x or p1=y)试试?

DEFAULT
DEFAULT
the selfish and the tyranny of evil men. Blessed is he who in the name of
charity and goodwill shepherds the weak through the valley of darkness, for
he is truly his brother’s keepe:

【在 v****s 的大作中提到】
: 谢谢各位!这是create table statement, 请帮忙看看如何提高select 的速度。
: 我只用这个语句:
: select * from shortest where ((p1=x and p2=y) or (p1=y and p2=y))
: delimiter $$
: CREATE TABLE `shortest` (
: `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
: `p1` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
: '',
: `p2` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
: '',

avatar
B*g
11
没有or多长时间?

DEFAULT
DEFAULT
the selfish and the tyranny of evil men. Blessed is he who in the name of
charity and goodwill shepherds the weak through the valley of darkness, for
he is truly his brother’s keepe:

【在 v****s 的大作中提到】
: 谢谢各位!这是create table statement, 请帮忙看看如何提高select 的速度。
: 我只用这个语句:
: select * from shortest where ((p1=x and p2=y) or (p1=y and p2=y))
: delimiter $$
: CREATE TABLE `shortest` (
: `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
: `p1` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
: '',
: `p2` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
: '',

avatar
B*g
12
你这个恐怕要create key(p2,p1)了

for

【在 a9 的大作中提到】
: 用select * from shortest where p2=y and (p1=x or p1=y)试试?
:
: DEFAULT
: DEFAULT
: the selfish and the tyranny of evil men. Blessed is he who in the name of
: charity and goodwill shepherds the weak through the valley of darkness, for
: he is truly his brother’s keepe:

avatar
v*s
13
select * from shortest where (p1=x and p2=y)
is also around 3 sec.

for

【在 B*****g 的大作中提到】
: 没有or多长时间?
:
: DEFAULT
: DEFAULT
: the selfish and the tyranny of evil men. Blessed is he who in the name of
: charity and goodwill shepherds the weak through the valley of darkness, for
: he is truly his brother’s keepe:

avatar
a9
14
估计只create key(p2)就行,key(p2,p1)不见得比p2快。

of
of

【在 B*****g 的大作中提到】
: 你这个恐怕要create key(p2,p1)了
:
: for

avatar
c*d
15
用explain select * from shortest where (p1=x and p2=y)
显示用pk上的index了吗?
我估计多半没用

【在 v****s 的大作中提到】
: select * from shortest where (p1=x and p2=y)
: is also around 3 sec.
:
: for

avatar
B*g
16
index没用上几百万数据3秒搞不完吧

【在 c*****d 的大作中提到】
: 用explain select * from shortest where (p1=x and p2=y)
: 显示用pk上的index了吗?
: 我估计多半没用

avatar
a9
17
没索引至少得半分钟了吧?

【在 B*****g 的大作中提到】
: index没用上几百万数据3秒搞不完吧
avatar
v*s
18
how to check this ?
my server is on win7, i'm using mysql workbench.
thanks!

【在 c*****d 的大作中提到】
: 用explain select * from shortest where (p1=x and p2=y)
: 显示用pk上的index了吗?
: 我估计多半没用

avatar
v*s
19
我今天改成了p1, p2各自建index,hash, 还是一样的速度。。。诡异。。。

【在 a9 的大作中提到】
: 估计只create key(p2)就行,key(p2,p1)不见得比p2快。
:
: of
: of

avatar
B*g
20
当然也不排除人家的server有32个cpu

【在 a9 的大作中提到】
: 没索引至少得半分钟了吧?
avatar
v*s
21
没。。。我现在dev的就一台8500 dual core, 3GHz...

【在 B*****g 的大作中提到】
: 当然也不排除人家的server有32个cpu
avatar
B*g
22
kick,就你这破机器3秒已经很快了。

the selfish and the tyranny of evil men. Blessed is he who in the name of
charity and goodwill shepherds the weak through the valley of darkness, for
he is truly his brother’s keepe:

【在 v****s 的大作中提到】
: 没。。。我现在dev的就一台8500 dual core, 3GHz...
avatar
c*d
23
就在mysql的命令行里执行explain select ...
或者你run一下select count(*) from table
和select count(p1) from table
看看执行时间是几秒

【在 v****s 的大作中提到】
: how to check this ?
: my server is on win7, i'm using mysql workbench.
: thanks!

avatar
c*d
24
百万这个数量级可以3秒以内完成
我在dell E4300 laptop core2 2.5GHz 4GB上的virtual linux + oracle
run一个select count(*) from m的操作
1,000,000花费00:00:00.33
100,000,000花费00:00:26.78
10,000,000这个数量级没测试,空间不够了
3秒应该没问题

【在 B*****g 的大作中提到】
: index没用上几百万数据3秒搞不完吧
avatar
a9
25
这这这,这主要得i/o强吧。

【在 B*****g 的大作中提到】
: 当然也不排除人家的server有32个cpu
avatar
a9
26
你count一个没有索引的列试试看?

【在 c*****d 的大作中提到】
: 百万这个数量级可以3秒以内完成
: 我在dell E4300 laptop core2 2.5GHz 4GB上的virtual linux + oracle
: run一个select count(*) from m的操作
: 1,000,000花费00:00:00.33
: 100,000,000花费00:00:26.78
: 10,000,000这个数量级没测试,空间不够了
: 3秒应该没问题

avatar
v*s
27
大哥,我老板不满意啊!
再说了,4 million,我用java后台写一个查询的都不用这么久吧?mysql这么搓??

for

【在 B*****g 的大作中提到】
: kick,就你这破机器3秒已经很快了。
:
: the selfish and the tyranny of evil men. Blessed is he who in the name of
: charity and goodwill shepherds the weak through the valley of darkness, for
: he is truly his brother’s keepe:

avatar
c*d
28
我试验的这个表没有索引, full table scan

【在 a9 的大作中提到】
: 你count一个没有索引的列试试看?
avatar
v*s
29
thanks folks !!
I've just tried
select count(*) from shortest where (p1=300 and p2=301);
Fetched time 3.19 sec...
something must be wrong....

【在 c*****d 的大作中提到】
: 百万这个数量级可以3秒以内完成
: 我在dell E4300 laptop core2 2.5GHz 4GB上的virtual linux + oracle
: run一个select count(*) from m的操作
: 1,000,000花费00:00:00.33
: 100,000,000花费00:00:26.78
: 10,000,000这个数量级没测试,空间不够了
: 3秒应该没问题

avatar
v*s
30
I've modified the index stuff today, here is the new one, which takes 3 sec
for count(*) ...
delimiter $$
CREATE TABLE `shortest` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`p1` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
'',
`p2` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT
'',
`dist` varchar(45) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL
DEFAULT '',
PRIMARY KEY (`id`),
KEY `p1` (`p1`) USING BTREE,
KEY `p2` (`p2`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4323060 DEFAULT CHARSET=latin1$$

【在 c*****d 的大作中提到】
: 我试验的这个表没有索引, full table scan
avatar
v*s
31
I tried this query:
explain select count(*) from shortest where (p1=300 and p2=301);
and here is the result:
id select_type table type possible_keys key key_len ref
rows Extra
1 SIMPLE shortest ALL p1,p2 NULL NULL NULL 4296656
Using where

【在 c*****d 的大作中提到】
: 就在mysql的命令行里执行explain select ...
: 或者你run一下select count(*) from table
: 和select count(p1) from table
: 看看执行时间是几秒

avatar
c*d
32
显示结果里type -> all
确定是full table scan的问题

ref


【在 v****s 的大作中提到】
: I tried this query:
: explain select count(*) from shortest where (p1=300 and p2=301);
: and here is the result:
: id select_type table type possible_keys key key_len ref
: rows Extra
: 1 SIMPLE shortest ALL p1,p2 NULL NULL NULL 4296656
: Using where

avatar
v*s
33
select count(*) from shortest;
5.211 sec

【在 c*****d 的大作中提到】
: 显示结果里type -> all
: 确定是full table scan的问题
:
: ref
:

avatar
v*s
34
explain select count(*) from shortest;
这个好像用到了index,结果里面写了。。。用了p1
id select_type table type possible_keys key key_len ref
rows Extra
1, SIMPLE, shortest, index, , p1, 47, , 4296656, Using index

【在 c*****d 的大作中提到】
: 就在mysql的命令行里执行explain select ...
: 或者你run一下select count(*) from table
: 和select count(p1) from table
: 看看执行时间是几秒

avatar
c*d
35
possible_keys -> p1
如果是用了索引, type -> index

ref

【在 v****s 的大作中提到】
: explain select count(*) from shortest;
: 这个好像用到了index,结果里面写了。。。用了p1
: id select_type table type possible_keys key key_len ref
: rows Extra
: 1, SIMPLE, shortest, index, , p1, 47, , 4296656, Using index

avatar
v*s
36
ok ic!
我感觉好像改变了index之后,performance一直都没有变过,说明table stat 没有
update???

【在 c*****d 的大作中提到】
: possible_keys -> p1
: 如果是用了索引, type -> index
:
: ref

avatar
c*d
37
“改变了index之后”,什么意思?

【在 v****s 的大作中提到】
: ok ic!
: 我感觉好像改变了index之后,performance一直都没有变过,说明table stat 没有
: update???

avatar
v*s
38
原来是p1p2一起index,(multiple index)
今天我改成对他们各自index。
参看我贴的两个create table statement.

【在 c*****d 的大作中提到】
: “改变了index之后”,什么意思?
avatar
c*d
39
哦,知道你的意思了
先看看p1的selective

【在 v****s 的大作中提到】
: 原来是p1p2一起index,(multiple index)
: 今天我改成对他们各自index。
: 参看我贴的两个create table statement.

avatar
B*g
40
just test in our develop server.
3xxM count 2 secs.
where on no index take 12 secs.
where on index take 0.078 ms

【在 c*****d 的大作中提到】
: 百万这个数量级可以3秒以内完成
: 我在dell E4300 laptop core2 2.5GHz 4GB上的virtual linux + oracle
: run一个select count(*) from m的操作
: 1,000,000花费00:00:00.33
: 100,000,000花费00:00:26.78
: 10,000,000这个数量级没测试,空间不够了
: 3秒应该没问题

avatar
a9
41
我记得count(*)是找索引count的来着呀?

爱 *//* 4. 一定要找

【在 B*****g 的大作中提到】
: just test in our develop server.
: 3xxM count 2 secs.
: where on no index take 12 secs.
: where on index take 0.078 ms

avatar
B*g
42
先statistic一下,然后在用hint用一下index试试。

【在 v****s 的大作中提到】
: 原来是p1p2一起index,(multiple index)
: 今天我改成对他们各自index。
: 参看我贴的两个create table statement.

avatar
v*s
43
谢谢,请具体点可以吗?我对mysql workbench还不是很熟

【在 B*****g 的大作中提到】
: 先statistic一下,然后在用hint用一下index试试。
avatar
c*d
46
count(*)为什么一定要找索引?
不可能的原因有,
1. 如果这个表没有一个col有index,肯定是full table scan
2. 至少在oracle,b-tree index里字段如果为null,index不会有相应的键值。如果
count(*),就算count(index_col)也不能用索引

【在 a9 的大作中提到】
: 我记得count(*)是找索引count的来着呀?
:
: 爱 *//* 4. 一定要找

avatar
B*g
47
问题回来了,为什么一个大table,没有pk?haha
咱公司的人最喜欢这样干。

【在 c*****d 的大作中提到】
: count(*)为什么一定要找索引?
: 不可能的原因有,
: 1. 如果这个表没有一个col有index,肯定是full table scan
: 2. 至少在oracle,b-tree index里字段如果为null,index不会有相应的键值。如果
: count(*),就算count(index_col)也不能用索引

avatar
c*d
48
我没太看懂
你这个试验怎么做的?
a table with 300+M rows
count(*) costs 2 seconds?
另外你count where on no index take 12 seconds
是select count(index_col) where col = value1
还是select index_col where col = value1?

【在 B*****g 的大作中提到】
: just test in our develop server.
: 3xxM count 2 secs.
: where on no index take 12 secs.
: where on index take 0.078 ms

avatar
B*g
49
hehe, 3.xxM
select count(*) from table
select count(*) from table where noindexcol = somevalue
select count(*) from table where indexcol = somevalue
And time is execution time from toad, not cpu time.

【在 c*****d 的大作中提到】
: 我没太看懂
: 你这个试验怎么做的?
: a table with 300+M rows
: count(*) costs 2 seconds?
: 另外你count where on no index take 12 seconds
: 是select count(index_col) where col = value1
: 还是select index_col where col = value1?

avatar
c*d
50
有点奇怪

这个2 seconds正常
这个为啥用了12 seconds?
0.078 seconds正常

【在 B*****g 的大作中提到】
: hehe, 3.xxM
: select count(*) from table
: select count(*) from table where noindexcol = somevalue
: select count(*) from table where indexcol = somevalue
: And time is execution time from toad, not cpu time.

avatar
B*g
51
That's why I think no index 3 secs is already very good.
After re-analyze, time reduce to 9 secs.

【在 c*****d 的大作中提到】
: 有点奇怪
:
: 这个2 seconds正常
: 这个为啥用了12 seconds?
: 0.078 seconds正常

avatar
c*d
52
没道理呀
select count(*) from table

select count(*) from table where noindexcol=val
都是full table scan
你这个table上面有pk?

【在 B*****g 的大作中提到】
: That's why I think no index 3 secs is already very good.
: After re-analyze, time reduce to 9 secs.

avatar
B*g
53
有.
update:
wr, select count(pk) from table need 11 secs.
update2:
no pk, sb remove pk for no reason.
but the column with not unique index even values are unique

【在 c*****d 的大作中提到】
: 没道理呀
: select count(*) from table
: 和
: select count(*) from table where noindexcol=val
: 都是full table scan
: 你这个table上面有pk?

avatar
v*s
54
大伙儿,我sb了,我弄错datatype了。。。。
今天早上让我们的database admin过来看了一会,他Y一眼就看到我的bug。。。太dumb
了。。。
我table里面用的是varchar(45),但是我的query里面是Int。。。
牛x的是Mysql居然偷偷摸摸的作了int to varchar的转换而没有让用户知道。。。
0.032sec...
包子发给了coolbid 和 beijing两位大哥了,谢谢你们的热心帮助!我学到了不少
index相关的知识!

【在 c*****d 的大作中提到】
: 有点奇怪
:
: 这个2 seconds正常
: 这个为啥用了12 seconds?
: 0.078 seconds正常

avatar
c*d
55
ft,怪不得select count(*) from table只用3秒
这个plan走pk,当然快了
你的试验说明在你们的机器上,3M数据全表扫描要10秒左右,稍微慢了点
select count(*) from table -- 3 sec pk index scan
select count(*) from table where indexcol -- 0.087 sec index scan
select count(*) from table where noindexcol -- 12 sec full table scan
你的select count(pk) from table在oracle里可以加hint
强制用pk,优化下来应该在3 sec以内

【在 B*****g 的大作中提到】
: 有.
: update:
: wr, select count(pk) from table need 11 secs.
: update2:
: no pk, sb remove pk for no reason.
: but the column with not unique index even values are unique

avatar
c*d
56
晕了,到底有还是没有?
最好还是看执行计划,用没用index,一目了然

【在 B*****g 的大作中提到】
: 有.
: update:
: wr, select count(pk) from table need 11 secs.
: update2:
: no pk, sb remove pk for no reason.
: but the column with not unique index even values are unique

avatar
B*g
57
question:
Why mysql not use index when varCol = CAST(intVal AS CHAR)

dumb

【在 v****s 的大作中提到】
: 大伙儿,我sb了,我弄错datatype了。。。。
: 今天早上让我们的database admin过来看了一会,他Y一眼就看到我的bug。。。太dumb
: 了。。。
: 我table里面用的是varchar(45),但是我的query里面是Int。。。
: 牛x的是Mysql居然偷偷摸摸的作了int to varchar的转换而没有让用户知道。。。
: 0.032sec...
: 包子发给了coolbid 和 beijing两位大哥了,谢谢你们的热心帮助!我学到了不少
: index相关的知识!

avatar
B*g
58
column is index as not unique. but it is a pk in production.

【在 c*****d 的大作中提到】
: 晕了,到底有还是没有?
: 最好还是看执行计划,用没用index,一目了然

avatar
c*d
59
那select count(*) from table不应该走index scan呀
都是full table scan
没道理比select count(*) from table where noindexcol快这么多

【在 B*****g 的大作中提到】
: column is index as not unique. but it is a pk in production.
avatar
B*g
60
not full table scan, it uses index fast full scan non-unique on that "pk"

【在 c*****d 的大作中提到】
: 那select count(*) from table不应该走index scan呀
: 都是full table scan
: 没道理比select count(*) from table where noindexcol快这么多

avatar
c*d
61
unique不能保证not null
optimizer如果用index fast full scan
怎么知道count(unique index col)中null值的个数?
虽然在你这个case里col原来曾经是pk

【在 B*****g 的大作中提到】
: not full table scan, it uses index fast full scan non-unique on that "pk"
avatar
B*g
62
that is why count(*) will use index
and count(pk) will full table scan and slow.
NND,
count(*) will use index on combined key, not index on pk.
seems oracle does everything right, and 准备打DBA的小报告。

【在 c*****d 的大作中提到】
: unique不能保证not null
: optimizer如果用index fast full scan
: 怎么知道count(unique index col)中null值的个数?
: 虽然在你这个case里col原来曾经是pk

avatar
a9
63
加cast就会用了吧。
sqlserver貌似也有这问题,就是如果一列是nvarchar的,那 column='abc'和column=N'
abc'
貌似速度完全不一样。

一定要找个能养我的PPMM */

【在 B*****g 的大作中提到】
: question:
: Why mysql not use index when varCol = CAST(intVal AS CHAR)
:
: dumb

avatar
v*s
64
because there is no index for intVal in my case! the index btree is built
ontop of varchar type.
but i don't know how mysql recognize this type error and convert it secretly
. that's why it took 3 sec,
converting int to varchar

【在 B*****g 的大作中提到】
: question:
: Why mysql not use index when varCol = CAST(intVal AS CHAR)
:
: dumb

avatar
a9
65
我记得count(*)是找最优索引来算的,呵呵。

一定要找个能养我的PPMM */

【在 B*****g 的大作中提到】
: that is why count(*) will use index
: and count(pk) will full table scan and slow.
: NND,
: count(*) will use index on combined key, not index on pk.
: seems oracle does everything right, and 准备打DBA的小报告。

avatar
B*g
66
it all based on that pk on table removed by someone.

【在 a9 的大作中提到】
: 我记得count(*)是找最优索引来算的,呵呵。
:
: 一定要找个能养我的PPMM */

相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。