Bug #26832 ENUM types not optimized
| Submitted: | 4 Mar 2007 18:17 | Modified: | 5 Apr 2011 5:46 |
|---|---|---|---|
| Reporter: | Roberto Spadim (Basic Quality Contributor) | Email Updates: | |
| Status: | Verified | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
| Version: | 5.5 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | ENUM OPTIMIZATION, qc | ||
[13 Apr 2007 13:08]
Valeriy Kravchuk
Thank you for a problem report, and sorry for a delay with its processing. Please, check with a newer version, 5.1.17, and, in case of the same problem, send a complete test case that demonstrates the behaviour described.
[13 May 2007 23:02]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[14 May 2007 4:10]
Valeriy Kravchuk
Roberto, Please, check with a newer version, 5.1.17, and, in case of the same problem, send a complete test case that demonstrates the behaviour described.
[14 Jun 2007 23:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[15 Jul 2007 23:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[16 Aug 2007 23:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[29 Mar 2011 18:50]
Roberto Spadim
the problem continue
create table with a ENUM field and select with a value that´s not in enum values
ok it´s nice to read raw values of myisam tables when crashed, but maybe a optimization could help us here, i don´t know if we will have problems, since a enum not null field with a value diferent from enum values isn´t a NULL value, it´s just a NOVALUE?! i don´t know what to do here hehe, maybe a warning when INSERT or UPDATE? i don´t know what to do with this
select * from mov_contacorrente where lote_tipo='beto' (2 seconds, 700000rows in table, full table scan)
create table:
CREATE TABLE `mov_contacorrente` (
`cc_hash_key` varchar(75) NOT NULL DEFAULT '',
`origem_tipo` enum('cob','doc','bc') NOT NULL DEFAULT 'doc',
`hash_origem` varchar(75) NOT NULL DEFAULT '',
`linha_digitavel` varchar(75) NOT NULL,
`plano_cobranca` int(10) unsigned NOT NULL DEFAULT '0',
`tipo_operacao` enum('tr','mp','cv','ie','ma','') NOT NULL DEFAULT '',
`tipo_cobranca` enum('dv','cd','cs') NOT NULL DEFAULT 'dv',
`evento_id` int(10) unsigned NOT NULL DEFAULT '0',
`sacador_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`sacador_id` bigint(20) NOT NULL DEFAULT '0',
`vendedor_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`vendedor_id` int(10) unsigned NOT NULL DEFAULT '0',
`credor_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`credor_id` bigint(20) NOT NULL DEFAULT '0',
`credor_ca` bigint(20) NOT NULL DEFAULT '0',
`credor_co` int(11) NOT NULL DEFAULT '0',
`credor_centro` bigint(20) NOT NULL DEFAULT '0',
`credor_conta` bigint(20) unsigned NOT NULL DEFAULT '0',
`credor_carteira` bigint(20) unsigned NOT NULL DEFAULT '0',
`credor_convenio` bigint(20) unsigned NOT NULL DEFAULT '0',
`devedor_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`devedor_id` bigint(20) NOT NULL DEFAULT '0',
`devedor_ca` bigint(20) NOT NULL DEFAULT '0',
`devedor_co` int(11) NOT NULL DEFAULT '0',
`devedor_centro` bigint(20) NOT NULL DEFAULT '0',
`devedor_conta` bigint(20) unsigned NOT NULL DEFAULT '0',
`devedor_carteira` bigint(20) unsigned NOT NULL DEFAULT '0',
`praca_pagamento_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`praca_pagamento_id` bigint(20) NOT NULL DEFAULT '0',
`liquidez` float(5,2) NOT NULL DEFAULT '0.00',
`prioridade_pgto` mediumint(3) unsigned NOT NULL DEFAULT '0',
`moeda` char(3) NOT NULL DEFAULT 'R$',
`valor_face` decimal(17,5) NOT NULL DEFAULT '0.00000',
`valor_residual` decimal(17,5) NOT NULL DEFAULT '0.00000',
`valor_residual_compensado` decimal(17,5) NOT NULL DEFAULT '0.00000',
`valor_emdigitacao` decimal(17,5) NOT NULL DEFAULT '0.00000',
`valor_pago_moeda_default` decimal(17,5) NOT NULL DEFAULT '0.00000',
`valor_pago_dinheiro_default` decimal(17,5) NOT NULL DEFAULT '0.00000',
`sit_cobranca` enum('n','s','l','lb') NOT NULL DEFAULT 'n',
`data_vencimento_face` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_emissao_face` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_vencimento_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_vencimento_credor` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_vencimento_devedor` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_vencimento_auto` enum('Y','N') NOT NULL DEFAULT 'N',
`data_entrada_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_entrada_credor` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_entrada_devedor` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_liquidacao_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_compensacao_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_compensacao_credor` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_compensacao_devedor` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_ultima_cobranca` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_proxima_cobranca` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`negativado` enum('Y','N') NOT NULL DEFAULT 'N',
`protestado` enum('Y','N') NOT NULL DEFAULT 'N',
`protesto_data` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`tabeliao_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`tabeliao_id` bigint(20) NOT NULL DEFAULT '0',
`multa_data_prevista` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`multa_data` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`multa_valor_tipo` enum('%','$','%rs') NOT NULL DEFAULT '%',
`multa_valor` decimal(17,5) NOT NULL DEFAULT '0.00000',
`multa_valor_cobrado` decimal(17,5) NOT NULL DEFAULT '0.00000',
`juros_data_prevista` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`juros_tipo` enum('$','%fs','%fc','%rs') NOT NULL DEFAULT '$',
`juros_valor` decimal(17,5) NOT NULL DEFAULT '0.00000',
`juros_periodo` mediumint(3) unsigned NOT NULL DEFAULT '1',
`juros_periodo_tipo` enum('dia','semana','mes','ano') NOT NULL DEFAULT 'dia',
`repasse_por` double NOT NULL DEFAULT '0',
`repasse_pessoa_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`repasse_pessoa_id` bigint(20) NOT NULL DEFAULT '0',
`contador_relacionamentos` int(10) unsigned NOT NULL DEFAULT '0',
`contador_repasse` int(10) unsigned NOT NULL DEFAULT '0',
`contador_ocorrencia` int(10) unsigned NOT NULL DEFAULT '0',
`contador_juros` int(10) unsigned NOT NULL DEFAULT '0',
`bordero` decimal(10,1) NOT NULL DEFAULT '0.0',
`lote_unidade` int(11) NOT NULL DEFAULT '0',
`lote_data` date NOT NULL DEFAULT '0000-00-00',
`lote_tipo` char(1) NOT NULL DEFAULT 'r',
`lote_numero` int(10) NOT NULL DEFAULT '0',
`digitador_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`digitador_id` bigint(20) NOT NULL DEFAULT '0',
`sit_spa` enum('d','s','p','a','mov') NOT NULL DEFAULT 'd',
`data_spa_d` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_spa_s` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_spa_p` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_spa_a` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_spa_mov` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`repasse_tipo` enum('total','cob') NOT NULL DEFAULT 'total',
`importado` varchar(25) NOT NULL,
`rodado` enum('Y','N') NOT NULL DEFAULT 'N',
`desconto_data_prevista` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`desconto_tipo` enum('$','%fs','%fc','%rs') NOT NULL DEFAULT '%fs',
`desconto_valor` decimal(17,5) NOT NULL DEFAULT '0.00000',
`pess_mov_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`pess_mov_id` int(10) unsigned NOT NULL DEFAULT '0',
`desconto_financeiro` decimal(17,5) NOT NULL DEFAULT '0.00000',
`imposto_retido` decimal(17,5) NOT NULL DEFAULT '0.00000',
`devedor_ca_descfin` int(11) NOT NULL DEFAULT '0',
`credor_ca_descfin` int(11) NOT NULL DEFAULT '0',
`devedor_ca_impret` int(11) NOT NULL DEFAULT '0',
`credor_ca_impret` int(11) NOT NULL DEFAULT '0',
`recompra_Valor` decimal(17,5) NOT NULL DEFAULT '0.00000',
`sit_venda_titulo` enum('','d','r','l') NOT NULL DEFAULT '',
`agente_financeiro_tipo` enum('f','j') NOT NULL DEFAULT 'f',
`agente_financeiro_id` int(11) NOT NULL DEFAULT '0',
`data_venda_bordero` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`data_recompra` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`cc_hash_key`),
KEY `origem` (`hash_origem`,`cc_hash_key`),
KEY `bordero` (`sacador_tipo`,`sacador_id`,`bordero`),
KEY `lote` (`lote_unidade`,`lote_data`,`lote_numero`),
KEY `devedor` (`devedor_tipo`,`devedor_id`,`data_vencimento_gmt`),
KEY `residual_devedor` (`valor_residual`,`devedor_tipo`,`devedor_id`),
KEY `credor_emi` (`credor_tipo`,`credor_id`,`data_emissao_face`),
KEY `devedor_emi` (`devedor_tipo`,`devedor_id`,`data_emissao_face`),
KEY `credor` (`credor_tipo`,`credor_id`,`data_vencimento_gmt`,`credor_convenio`),
KEY `vencimento` (`data_vencimento_gmt`),
KEY `venc` (`data_vencimento_gmt`,`cc_hash_key`),
KEY `emi` (`data_emissao_face`,`cc_hash_key`),
KEY `t_bol` (`evento_id`,`lote_tipo`,`importado`,`cc_hash_key`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
PARTITIONS 4 */
[29 Mar 2011 18:50]
Roberto Spadim
stay with this problem in mysql 5.5 changing to performace not serious
[3 Apr 2011 12:17]
Valeriy Kravchuk
I had never seen complete, correct and repeatable test case in this bug report. In your last table the column you refer to is NOT ENUM:
`lote_tipo` char(1) NOT NULL DEFAULT 'r',
and is NOT indexed. Why do you expect anything else bug full table scan is beyond my understanding.
In my test simple test case:
mysql> show create table te\G
*************************** 1. row ***************************
Table: te
Create Table: CREATE TABLE `te` (
`c1` enum('a','b','c') DEFAULT NULL,
`c2` int(11) DEFAULT NULL,
KEY `c1` (`c1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> insert into te values('1',1),('2',2);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into te select * from te;
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into te select * from te;
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> insert into te select * from te;
Query OK, 8 rows affected (0.00 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> insert into te select * from te;
Query OK, 16 rows affected (0.00 sec)
Records: 16 Duplicates: 0 Warnings: 0
mysql> insert into te select * from te;
Query OK, 32 rows affected (0.01 sec)
Records: 32 Duplicates: 0 Warnings: 0
mysql> insert into te select * from te;
Query OK, 64 rows affected (0.01 sec)
Records: 64 Duplicates: 0 Warnings: 0
mysql> insert into te select * from te;
Query OK, 128 rows affected (0.02 sec)
Records: 128 Duplicates: 0 Warnings: 0
mysql> insert into te values('3',3);
Query OK, 1 row affected (0.00 sec)
mysql> explain select * from te where c1 = '3';
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | te | ref | c1 | c1 | 2 | const | 1 | Using where |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.02 sec)
mysql> explain select * from te where c1 = '1';
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | te | ref | c1 | c1 | 2 | const | 128 | Using where |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from te where c1 = '4';
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | te | ref | c1 | c1 | 2 | const | 1 | Using where |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
I see expected results. Even though '4' is not a valid value for ENUM, index is used to search for it, and will aloow to find out fast enough zero rows with this value exist.
Is this just a feature request to check if value for ENUM column is valid one even before optimization? Please, clarify.
[3 Apr 2011 15:42]
Roberto Spadim
sorry about no test case, i will try to explain with your example
------
... all insert´s / create table on your example was done ... continuing ...
insert into te values('g',1),('f',2);
/* 2 rows affected, 0 rows found. Duration for 2 queries: 0,093 sec. */
sql_mode: PIPES_AS_CONCAT,ALLOW_INVALID_DATES
show warnings;
"Level","Code","Message"
"Warning","1265","Dado truncado para coluna 'c1' na linha 1"
"Warning","1265","Dado truncado para coluna 'c1' na linha 2"
------
no problems... it´s what i want... but there´s a 'default' value when truncate occur (i don´t know if it´s a null value, or '' or 0 index of enum field, but we can select it with where c1=0 or c1='' sometimes, i didn´t checked this in mysql docs) check:
------
select * from te ;
"c1","c2"
... some values are repeated....
"a","1"
"b","2"
"c","3"
... last two rows: ...
"","1"
"","2"
------
"" -> the 'default' value for truncated field (ok no problems)
the problem is:
------
select * from te where c1 = 'g';
the result:
/* 0 rows affected, 0 rows found. Duration for 1 query: 0,093 sec. */
but check that no optimization was done
explain select * from te where c1 = 'g';
"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
"1","SIMPLE","te","ALL",NULL,NULL,NULL,NULL,"261","Using where"
------
full table scan!? 261 rows!
i was thinking about something like this result:
------
delete from te;
explain select * from te where c1 = 'g';
"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
"1","SIMPLE",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"Impossible WHERE noticed after reading const tables"
------
no row scan since c1='g' don´t exists and it´s not a default value for truncated values c1=0 or c1='' for example
but check that this works: (without deleting before...)
------
this: select * from te where c1=0
and this: select * from te where c1=''
result the same values for truncated values (i think it´s ok):
"c1","c2"
"","1"
"","2"
------
nice, it´s what i want too select with 'default' truncated value for enum
.............................
the optimization idea:
select * from te where c1=0 or select * from te where c1=''
use the default 'truncated' value like today implementation, no changes/feature request here
but if it´s a truncated value where
select * from te where c1='abc' (c1='abc' will return 0 rows)
check if enum('abc') exists (default truncated values are alowed like c1=0 or c1='')
if not c1='abc' should be rewrite as something like '0=1'
like this:
------
explain select * from te where 0=1
"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
"1","SIMPLE",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"Impossible WHERE"
------
no full table scan! :)
c1='abc' is a impossible WHERE
but c1='' or c1=0 isn´t a impossible WHERE for truncated values (nice!)
result: no full table scan for enum fields
this is good for some alter table, and not optimized app
i don´t know if it´s easy to implement, but it´s a good optimization for 'bad' coded apps
[3 Apr 2011 15:45]
Roberto Spadim
don´t need index here
[3 Apr 2011 16:24]
Valeriy Kravchuk
OK, we have a reasonable feature request here for new kind of "Impossible WHERE" check for ENUMs.
[3 Apr 2011 18:25]
Roberto Spadim
nice! :) any help contact me =)
[3 Apr 2011 18:28]
Roberto Spadim
this apply to SET() type too? i never used SET i preffer two tables (1:N tables with foreign key for this, or app serialization) could you test it? i don´t know how to use SET fields
[5 Apr 2011 5:46]
Roberto Spadim
changed to any OS need some test with SET field type but ENUM type optimizer 'work', is near to set type 'work'
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.073 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
Description: enum types not optimized when i search a value that don't bellow to enum values, like enum('a','b','c') select * from table where enum_field='d' this make an table scan or index scan, see the screnshots from my query How to repeat: create a table with enum and search with a non enum value Suggested fix: when using enum fields check it and make a 0 rows optimization before start table scan optimizations