Hello experts,
I developped sometimes ago an indexer + search engine with mysql.
Now the database weight is 15Go and the query on it became sometimes very long.
For today on 75 request 24 are longer than 2 seconds :
SELECT * FROM `vtpLog` where `timeResponse` > 2 order by date desc; Time ResultCountvétérinaire 126.35 54482perte d'identité 8.76 948%de femmes vétérinaires 9.04 73pancreatite rat 3.23 23dépilation chinchilla 3.75 1trichophyton 3.2 319tumeur de la prostate 8.63 96pathologies du dindon 2.26 15Hypothyroidie canine 3.62 274gestation de la chienne 18.49 363vermifugation chienne 4.53 26vermifugation chienne gestante 6.33 9hypothyroidie 5.07 1032acupuncture 18.33 11association antibiotiques 26.63 1055pyothorax chat 5.68 45</pre>
When mysql takes long time to respond the servers state seems ok :
cpu : 20 - 40 %
mem : 1.7Go used, 2Go Page cache, 300mo free
hdd : reading only
I documented myself, tuned-up mysql, re-check indexes for month but no real progress confused: so I'd like an mysql expert advice to tell me what I've done stupid )
I don't plan (for now) to recode all to use "full text".
So here are the informations :
Server :
This server is dedicated for this search engine; there are only apache + mysql with maximum memory allocated on mysql.
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
CPU : Core(TM)2 E8400 @3.00GHz GenuineIntel
MEM : 4 Go DDR2
HDD : 2x 750 Go - SATA2 (RAID 1)
</td></tr></table>
Script :
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
/*================================================= ========= ====*/
create table vtpCategory
(
Id int not null auto_increment,
Parent_Id int,
Value varchar(254),
primary key (Id)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpDomain
(
Id int not null auto_increment,
vtpCategory_Id int not null,
IsOff bool default 0 ,
LastFarmSuccess bool default 0 ,
Rank int default 50,
StartUri varchar(254) not null ,
Title varchar(254) ,
Language varchar(254) ,
LastVisitDate datetime ,
primary key (Id),
key AK_StartUriUnique (StartUri)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpHtmlSource
(
Id int not null auto_increment,
Uri_Id int,
Value mediumtext,
primary key (Id)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpUri
(
Id int not null auto_increment,
Domain_Id int not null,
Value varchar(2040) not null,
ValueHash int not null,
IsDead bool default 0 ,
Content mediumtext ,
ContentHash int,
Title varchar(254) ,
Description varchar(254) ,
UpdateDate datetime ,
Rank int default 0 ,
primary key (Id),
key AK_ValueHash (ValueHash)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpUriOutsideDomain
(
Id int not null auto_increment,
Domain_Id int,
Value varchar(254),
ValueHash int,
FromUriValueHash int ,
FromUriValue varchar(254) ,
primary key (Id)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpWord
(
Id int not null auto_increment,
Value varbinary (254) not null ,
primary key (Id),
key AK_Value (Value)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpWordScore
(
Uri_Id int not null,
Word_Id int not null,
Score int ,
primary key (Uri_Id, Word_Id)
)
type = MyISAM;
alter table vtpCategory add constraint FK_CategoryCategory foreign key (Parent_Id)
references vtpCategory (Id) on delete restrict on update restrict;
alter table vtpDomain add constraint FK_DomainCategory foreign key (vtpCategory_Id)
references vtpCategory (Id) on delete restrict on update restrict;
alter table vtpHtmlSource add constraint FK_HtmlSourceUri foreign key (Uri_Id)
references vtpUri (Id) on delete restrict on update restrict;
alter table vtpUri add constraint FK_UriDomain foreign key (Domain_Id)
references vtpDomain (Id) on delete restrict on update restrict;
alter table vtpUriOutsideDomain add constraint FK_OutsideDomainDomain foreign key (Domain_Id)
references vtpDomain (Id) on delete restrict on update restrict;
alter table vtpWordScore add constraint FK_Uri foreign key (Uri_Id)
references vtpUri (Id) on delete restrict on update restrict;
alter table vtpWordScore add constraint FK_Word foreign key (Word_Id)
references vtpWord (Id) on delete restrict on update restrict;
</td></tr></table>
Query in two times :
1- get WordIds
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
SELECT Id FROM vtpWord WHERE (CAST(vtpWord.Value AS CHAR CHARACTER SET utf8) = 'vétérinaire');
</td></tr></table>
Returns 41 here;
This one is quite fast (0.1610 sec without query cache)
2- sort by scores
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
SET SESSION SQL_BIG_SELECTS = 1;
SELECT SQL_CALC_FOUND_ROWS
vtpUri.Id as UriId,
SUM( ws0.Score) * (vtpDomain.Rank + vtpUri.Rank) as uriScore,
vtpUri.Domain_Id
FROM
vtpUri
INNER JOIN vtpWordScore AS ws0 ON (ws0.Uri_Id = vtpUri.Id)
INNER JOIN vtpDomain ON (vtpDomain.Id = vtpUri.Domain_Id) where ws0.Word_Id = 41 AND vtpDomain.vtpCategory_Id != 2 AND vtpDomain.IsOff != 1
GROUP BY ws0.Uri_Id
ORDER BY uriScore desc LIMIT 0,400
</td></tr></table>
Mysql States :
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
MySQL work since 35 Days 5 hours 16 minutes 15 seconds.
Slow_queries 4 304
Handler_read_rnd 1 670 k
Handler_read_rnd_next 19 G
Created_tmp_disk_tables 1 765
Opened_tables 157
Table_locks_waited 829 k
</td></tr></table>
my.cnf :
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
skip-locking
max_connections = 40
key_buffer_size = 2500M # cf mysqltuner.pl
max_allowed_packet = 500M
table_cache = 200 # table_open_cache empeche de demarrer
open_files_limit = 600 # il y avais 4200 # should typically be set to at least 2x-3x of table_cache
sort_buffer_size = 4M
read_buffer_size = 4M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 32M
thread_cache_size = 8
query_cache_size = 16M # == query_cache_limit
query_cache_limit = 16M
join_buffer_size = 3M
low_priority_updates = 1
tmp_table_size = 3400M # doit == max_heap_table_size
max_heap_table_size = 3400M
#net_buffer_length = 8K
#skip-external-locking
#log-slow-queries = /var/log/mysql/slow_queries.log
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
</td></tr></table>
I hope you can show me the light
I developped sometimes ago an indexer + search engine with mysql.
Now the database weight is 15Go and the query on it became sometimes very long.
For today on 75 request 24 are longer than 2 seconds :
SELECT * FROM `vtpLog` where `timeResponse` > 2 order by date desc; Time ResultCountvétérinaire 126.35 54482perte d'identité 8.76 948%de femmes vétérinaires 9.04 73pancreatite rat 3.23 23dépilation chinchilla 3.75 1trichophyton 3.2 319tumeur de la prostate 8.63 96pathologies du dindon 2.26 15Hypothyroidie canine 3.62 274gestation de la chienne 18.49 363vermifugation chienne 4.53 26vermifugation chienne gestante 6.33 9hypothyroidie 5.07 1032acupuncture 18.33 11association antibiotiques 26.63 1055pyothorax chat 5.68 45</pre>
When mysql takes long time to respond the servers state seems ok :
cpu : 20 - 40 %
mem : 1.7Go used, 2Go Page cache, 300mo free
hdd : reading only
I documented myself, tuned-up mysql, re-check indexes for month but no real progress confused: so I'd like an mysql expert advice to tell me what I've done stupid )
I don't plan (for now) to recode all to use "full text".
So here are the informations :
Server :
This server is dedicated for this search engine; there are only apache + mysql with maximum memory allocated on mysql.
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
CPU : Core(TM)2 E8400 @3.00GHz GenuineIntel
MEM : 4 Go DDR2
HDD : 2x 750 Go - SATA2 (RAID 1)
</td></tr></table>
Script :
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
/*================================================= ========= ====*/
create table vtpCategory
(
Id int not null auto_increment,
Parent_Id int,
Value varchar(254),
primary key (Id)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpDomain
(
Id int not null auto_increment,
vtpCategory_Id int not null,
IsOff bool default 0 ,
LastFarmSuccess bool default 0 ,
Rank int default 50,
StartUri varchar(254) not null ,
Title varchar(254) ,
Language varchar(254) ,
LastVisitDate datetime ,
primary key (Id),
key AK_StartUriUnique (StartUri)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpHtmlSource
(
Id int not null auto_increment,
Uri_Id int,
Value mediumtext,
primary key (Id)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpUri
(
Id int not null auto_increment,
Domain_Id int not null,
Value varchar(2040) not null,
ValueHash int not null,
IsDead bool default 0 ,
Content mediumtext ,
ContentHash int,
Title varchar(254) ,
Description varchar(254) ,
UpdateDate datetime ,
Rank int default 0 ,
primary key (Id),
key AK_ValueHash (ValueHash)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpUriOutsideDomain
(
Id int not null auto_increment,
Domain_Id int,
Value varchar(254),
ValueHash int,
FromUriValueHash int ,
FromUriValue varchar(254) ,
primary key (Id)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpWord
(
Id int not null auto_increment,
Value varbinary (254) not null ,
primary key (Id),
key AK_Value (Value)
)
type = MyISAM;
/*================================================= ========= ====*/
create table vtpWordScore
(
Uri_Id int not null,
Word_Id int not null,
Score int ,
primary key (Uri_Id, Word_Id)
)
type = MyISAM;
alter table vtpCategory add constraint FK_CategoryCategory foreign key (Parent_Id)
references vtpCategory (Id) on delete restrict on update restrict;
alter table vtpDomain add constraint FK_DomainCategory foreign key (vtpCategory_Id)
references vtpCategory (Id) on delete restrict on update restrict;
alter table vtpHtmlSource add constraint FK_HtmlSourceUri foreign key (Uri_Id)
references vtpUri (Id) on delete restrict on update restrict;
alter table vtpUri add constraint FK_UriDomain foreign key (Domain_Id)
references vtpDomain (Id) on delete restrict on update restrict;
alter table vtpUriOutsideDomain add constraint FK_OutsideDomainDomain foreign key (Domain_Id)
references vtpDomain (Id) on delete restrict on update restrict;
alter table vtpWordScore add constraint FK_Uri foreign key (Uri_Id)
references vtpUri (Id) on delete restrict on update restrict;
alter table vtpWordScore add constraint FK_Word foreign key (Word_Id)
references vtpWord (Id) on delete restrict on update restrict;
</td></tr></table>
Query in two times :
1- get WordIds
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
SELECT Id FROM vtpWord WHERE (CAST(vtpWord.Value AS CHAR CHARACTER SET utf8) = 'vétérinaire');
</td></tr></table>
Returns 41 here;
This one is quite fast (0.1610 sec without query cache)
2- sort by scores
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
SET SESSION SQL_BIG_SELECTS = 1;
SELECT SQL_CALC_FOUND_ROWS
vtpUri.Id as UriId,
SUM( ws0.Score) * (vtpDomain.Rank + vtpUri.Rank) as uriScore,
vtpUri.Domain_Id
FROM
vtpUri
INNER JOIN vtpWordScore AS ws0 ON (ws0.Uri_Id = vtpUri.Id)
INNER JOIN vtpDomain ON (vtpDomain.Id = vtpUri.Domain_Id) where ws0.Word_Id = 41 AND vtpDomain.vtpCategory_Id != 2 AND vtpDomain.IsOff != 1
GROUP BY ws0.Uri_Id
ORDER BY uriScore desc LIMIT 0,400
</td></tr></table>
Mysql States :
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
MySQL work since 35 Days 5 hours 16 minutes 15 seconds.
Slow_queries 4 304
Handler_read_rnd 1 670 k
Handler_read_rnd_next 19 G
Created_tmp_disk_tables 1 765
Opened_tables 157
Table_locks_waited 829 k
</td></tr></table>
my.cnf :
<table border="0" align="center" width="90%" cellpadding="3" cellspacing="1"><tr><td class="SmallText">Quote:</td></tr><tr><td class="quote">
skip-locking
max_connections = 40
key_buffer_size = 2500M # cf mysqltuner.pl
max_allowed_packet = 500M
table_cache = 200 # table_open_cache empeche de demarrer
open_files_limit = 600 # il y avais 4200 # should typically be set to at least 2x-3x of table_cache
sort_buffer_size = 4M
read_buffer_size = 4M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 32M
thread_cache_size = 8
query_cache_size = 16M # == query_cache_limit
query_cache_limit = 16M
join_buffer_size = 3M
low_priority_updates = 1
tmp_table_size = 3400M # doit == max_heap_table_size
max_heap_table_size = 3400M
#net_buffer_length = 8K
#skip-external-locking
#log-slow-queries = /var/log/mysql/slow_queries.log
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
</td></tr></table>
I hope you can show me the light

Comment