ft_min_word_len set in local my.cnf? - mysql

Is it possible to set ft_min_word_len for a certain user (such as by placing a my.cnf file in the user home dir with ft_min_word_len set)? The documentation says I need to restart the server after making this change, but a user does not have access to do that.

I'm working with this now, so to add as a reference for anyone looking at this...
You can use this query in a query
browser or the MySQL prompt to show
the state of ft_min_word_len: "SHOW
VARIABLES LIKE 'ft_min_word_len';"
ft_min_word_len deafults to a value
of '4' and is not by default listed
in "my.cnf". To change it's default
value, add: "ft_min_word_len = 3" to
my.cnf under the [mysqld] section.
After changing the value of
ft_min_word_len, the server must be
restarted.
After changing the value of
ft_min_word_len, any indexes you have
must be rebuilt
A fast way to rebuild an index is to
use this query: "REPAIR TABLE
your_table_name QUICK;" Note:
You're using the name of the table
only, not the name of any indexes.
If you have more than one index
against the 'your_table_name' table,
all of them will be re-built.

No, it's not possible, because it changes how the fulltext indices are built. It takes effect at index generation, not (only) at query time.
FYI: Not only do you have to restart the server, you have to rebuild all your fulltext indices after changing it.

Related

How to turn off index merge, MySQL

I encounter a dead lock problem when updating a separate records in two transactions.
According to our diagnose, it should be caused by index merge.
And
select ##optimizer_switch;
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on....
indeed shows the index merge is on . So we hope to turn off it. But I cannot find the command, can anyone give me an answer?
Thanks!
It is given in the Documentation:
To change the value of optimizer_switch, assign a value consisting of
a comma-separated list of one or more commands:
SET [GLOBAL|SESSION] optimizer_switch='command[,command]...';
Try the following to disable it Globally:
SET GLOBAL optimizer_switch='index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off';
Personally I never used it but I found this in the reference manual, maybe can help you:
https://dev.mysql.com/doc/refman/5.7/en/switchable-optimizations.html
SET [GLOBAL|SESSION] optimizer_switch='command[,command]...';
Each command value should have one of the forms shown in the following table.
Command Syntax Meaning
default Reset every optimization to its default value
opt_name=default Set the named optimization to its default value
opt_name=off Disable the named optimization
opt_name=on Enable the named optimization

Disable MySQL fulltext search stopwords in innodb

I am using a FullText index on MySQL v5.6 InnoDB table.
and running this query to perform search on the table
SELECT * FROM `table` WHERE MATCH(title,desc) AGAINST ('+hello -for' IN BOOLEAN MODE);
when i run the above query it still gives me the results which includes word for in the title or desc.
I have already made the following changes in my my.cnf file to avoid stopwords.
innodb_ft_min_token_size=2
ft_min_word_len=2
ft_stopword_file = ""
Why i am still getting results with word for included in it?
You need to ensure that the server variable innodb_ft_enable_stopword is set to OFF if you aren't wanting to use stop words at all.
SET ##SESSION.innodb_ft_enable_stopword = 'OFF';

MySQL error: The maximum column size is 767 bytes

When I run a program which does something with MySQL, I got this error message:
2015-06-10 15:41:12,250 ERROR app.wsutils 419 INCRON: Error: ('HY000',
'[HY000] [MySQL][ODBC 5.2(w) Driver][mysqld-5.7.7-rc-log]Index column
size too large. The maximum column size is 767 bytes. (1709)
(SQLExecDirectW)')
I Googled a little bit and found this error might be related to the innodb_large_prefix option. However, I am using MySQL 5.7.7 RC, which has already set innodb_large_prefix to be "ON" (checked in MySQL Workbench), allowing up to 3072 bytes. I am not sure if that is the problem with innodb_large_prefix or not.
Anyway, does anyone have an idea how to fix this problem?
From Wamp Version 3.2.6
Just edit this file:
C:\wamp64\bin\mysql\mysql8.0.27\my.ini
Change the config for innodb-default-row-format value
from innodb-default-row-format=compact
to innodb-default-row-format=dynamic
Restart mysql
With the help of the answer given by BK435, I did the following and solved the problem.
set global innodb_file_format = BARRACUDA;
set global innodb_large_prefix = ON;
create table test (........) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
Your column that you are trying to index is too large and your settings must not be correct for innodb_large_prefix. There are a couple prerequisites parameters that also have to be set in order for innodb_large_prefix to work correctly.
You can check to make sure that innodb_large_prefix is set by running:
show global variables like 'innodb_lar%';
Here are a couple prerequisites for using innodb_large_prefix:
You need to set your global variable innodb_file_format=BARRACUDA
to check settings run: show global variables like 'innodb_fil%';
At the table level you have to use ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED
for Innodb, rows are stored in COMPACT format (ROW_FORMAT=COMPACT) by default.
I was using MariaDB version 10.1.38 and used all of the below given commands but it did not work -
set global innodb_large_prefix = ON;
Query OK, 0 rows affected (0.00 sec)
set global innodb_file_per_table = ON;
Query OK, 0 rows affected (0.00 sec)
set global innodb_file_format = Barracuda;
Query OK, 0 rows affected (0.00 sec)
SET GLOBAL innodb_default_row_format = 'DYNAMIC';
Because after you restart your MySQL (or MariaDB), these settings will not reflect back using the command at the mysql prompt: show variables like 'innodb%';
Then I edited My.ini and added these settings in the file at below location-
C:\xampp\mysql\bin\my.ini
## Innodb settings to bypass error of max size 737
innodb-file-format=barracuda
innodb-file-per-table=ON
innodb-large-prefix=ON
## Above 3 didnot work so i added below
innodb_default_row_format = 'DYNAMIC'
source:https://www.experts-exchange.com/questions/28675824/Why-am-I-unable-to-turn-innodb-large-prefix-ON-successfully-Every-time-I-reboot-mySql-on-my-Ubuntu-VPS-it-resets-to-OFF.html
For me using Mariadb 10.1.31, just add this while you login in Mysql CLI:
SET GLOBAL innodb_file_format = Barracuda;
SET GLOBAL innodb_file_per_table = ON;
SET GLOBAL innodb_large_prefix = ON;
SET GLOBAL innodb_default_row_format = 'DYNAMIC';
Just add the following options to my.cnf
[mysqld]
innodb_file_format=Barracuda
innodb_file_per_table=1
innodb_large_prefix=1
Then, restart mysql server the problem will be resolved.
You need to change the innodb-default-row-format variable to dynamic.
If you are using phpMyAdmin, navigate to variables and search for row format.
If you are using WampServer, navigate to my.ini file like:
C:\wamp64\bin\mysql\mysql8.0.27\my.ini
For more info, visit MySQL Manual
This worked for me:
From Wamp Version 3.2.6
Just edit this file: C:\wamp64\bin\mysql\mysql8.0.27\my.ini
Change the config for innodb-default-row-format value
from innodb-default-row-format=compact
to innodb-default-row-format=dynamic
Restart mysql
Go to mysql config in this file my.cnf
change this line
innodb-default-row-format=compact
to
innodb-default-row-format=dynamic
I had the same error despite having innodb_large_prefix configured correctly.
The issue was in used collation. My db had default collation set to utf8mb4_bin (you can check it in phpmyadmin "Operations" tab for database). It means it uses 4 bytes per char, while utf8 collation (e.g. utf8_unicode_ci) uses 3 bytes per char.
in this case you can either use different collation e.g. by adding DEFAULT CHARSET=utf8 at the end of the CREATE TABLE statement, or limit the index size by using just a part of the column value
like KEY 'identifier' (column1(5),column2(10)).
See also related question: #1071 - Specified key was too long; max key length is 767 bytes
In my case (MySQL version 5.6) the issue was that I was trying to create a table with a column that can have up to 256 characters (the db uses utf8 collation), so 3 bytes per 1 utf8 character = 256*3=768 bytes. The fix was to simply have 255 characters instead of 256.
I could also set innodb_large_prefix, like others suggest, but in my case it was easier to just have fewer symbols.
Just like #sasank-mukkamala said , for me only adding ROW_FORMAT=DYNAMIC to create command did it rightly.
create table `NameOfTheTable` (........) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
Im using Mysql 5.7
Click PHPMyAdmin (home)
Click Variables
On innodb default row formart, click edit then enter 2, then click save
It will show variable value as dynamic
Import table again
I had this problem because I tried to create a String primary key with varchar(254). Easy to overlook sometimes.. So double check your index type and length as well :)
In case someone is working with MySQL 5.6 the only solution that I found was to update to MySQL 5.7 and setting my.cnf as mentioned in previous comments (https://stackoverflow.com/a/57465002/2300390).
I had the same error but on a different issue. I got this error while importing a data (data and schema) script. Deleting the Unique Index fixed the issue for me.
Answer taken from this link
Set the below system variables:
innodb_buffer_pool_size.................................... 702545920
innodb_file_format......................................... Barracuda
innodb_file_format_check................................... ON
innodb_file_format_max..................................... Barracuda
innodb_file_per_table...................................... ON
innodb_large_prefix........................................ ON
innodb_log_file_size....................................... 50331648
Also, make sure when you create your schema you create it as Latin1. That is what finally fixed me.

How to allow empty string for integer in MySQL?

I have integer fields in a table. The POSTs are sent by a complicated JavaScript. They send empty strings like "" but as you guessed MySQL doesn't allow empty strings in integer fields. Are there any options to allow empty strings? Like if it takes an empty string it will save it as NULL.
There are 2 ways to do this.
For Current Mysql Session (Temporary Solution)
First execute query to get current SQL mode of your mysql server.
mysql> SELECT ##sql_mode;
+----------------------------------------------------------------+
| ##sql_mode |
+----------------------------------------------------------------+
|STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
If result contains STRICT_TRANS_TABLES, you have to remove that value to allow insert query to pass NULL value. Make sure your mysql User have privileges to apply this changes and restart Mysql Server after applying this.
SET GLOBAL sql_mode = '';
For Life Time of Mysql (Permanent Solution)
You have to update my.cnf file. Location of that file is : \etc\my.cnf or \etc\mysql\mysql.cnf
There will be some default parameters set under [mysqld] like
[mysqld]
innodb_file_per_table=1
default-storage-engine=MyISAM
performance-schema=0
max_allowed_packet=268435456
open_files_limit=10000
Just add one line under that
sql-mode=""
Make sure to restart Mysql Server after changing this file. Normally root user will be the owner of file so you have to login with root user on server.
For more details to understand what this SQL mode do.
STRICT_TRANS_TABLES
Enable strict SQL mode for transactional storage engines, and when possible for non-transactional storage engines. For details, see Strict SQL Mode.
Refer : http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_strict_trans_tables
NO_AUTO_CREATE_USER
Prevent the GRANT statement from automatically creating new user accounts if it would otherwise do so, unless authentication information is specified. The statement must specify a nonempty password using IDENTIFIED BY or an authentication plugin using IDENTIFIED WITH.
Refer: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_auto_create_user
NO_ENGINE_SUBSTITUTION
Control automatic substitution of the default storage engine when a statement such as CREATE TABLE or ALTER TABLE specifies a storage engine that is disabled or not compiled in.
Refer : http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_engine_substitution
Removing sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" from my.ini has solved the issue.
Edit: Removing the line above works but it is a bad idea. It allows to have things like 0000-00-00 or empty string dates. Better keep the line above and don't insert empty sting into an integer field, instead convert empty string into NULL and then insert that NULL into integer field.
Assuming that the column allows for NULL values, you must explicitly tell MySQL to use a value of NULL, rather than passing an empty string (which is cast to 0):
INSERT INTO table (column_name) VALUES (NULL);

ignoring mysql fulltext stopwords in query

I'm building a search for a site, which utilizes a fulltext search. The search itself works great, that's not my problem. I string together user provided keywords (MATCH... AGAINST...) with AND's so that multiple words further narrow the results. Now, I know that certain stop words aren't indexed, and that's fine with me I don't really want to use them as selection criteria. But, if a stopword is provided in the keyword set (by the user), it kills all the results (as expected) even if the word actually is in a certain text block.
My question: is there any way to check to see if a certain word is a stop word at the time of the query? My preferred solution would just be to exclude the relevant word from the search criteria (I don't care if a user can narrow results by the word 'neither', I just don't want MySQL to return an empty result set because the user provided it, even though neither does exist in the results). Or, am I just going to have to empty the stopword list? Thanks very much for any help.
edit ----
I'm sorry, but there's really no code snippets to provide for this one. The code works fine, actually exactly as expected. It's more of a logical problem I'm dealing with. But as an example, in the way of explanation:
lets say there are three records, which include the words (but are not limited to)
1: apple, orange, mango, banana
2: grape, orange, pineapple, mango
3: potato, mango, melon, keira knightly
If the search word entered by the user is mango, all results are returned correctly. If the words are orange AND mango, results 1 and 2 are returned (correctly). Now, let's say banana is a stop word (it's not... but let's assume it is), if the search is for orange, mango, AND banana, no results are returned (because banana isn't in the fulltext index).
What I'm looking for is if anyone else has encountered this problem, and has a way to work around it. Sort of an:
if 'banana' NOT STOP WORD match 'banana' against `words`. (OBVIOUSLY not real code).
Or... am I just going to have to drop the stopword list...
You can verify the keywords by comparing all stopwords. Here is the list of stopwords
I've found out a solution to disable stopwords from fulltext.
You just need to locate .cnf file and add this,
ft_stopword_file = ""
restart mysql engine and rebuild indexes;
Hope this work
How to disable fulltext stopwords in MySQL:
In my.ini text file (MySQL) :
ft_stopword_file = "" or link an empty file "empty_stopwords.txt"
ft_min_word_len = 2
// set your minimum length, but be aware that shorter words (3,2) will increase the query time dramatically, especially if the fulltext indexed column fields are large.
Save the file, restart the server.
The next step should be to repair the indexes with this query:
REPAIR TABLE tbl_name QUICK.
However, this will not work if you table is using InnoDB storage engine. You will have to change it to MyISAM :
ALTER TABLE t1 ENGINE = MyISAM;
So, once again:
1. Edit my.ini file and save
2. Restart your server (this cannot be done dynamically)
3. Change the table engine (if needed) ALTER TABLE tbl_name ENGINE = MyISAM;
4. Perform repair REPAIR TABLE tbl_name QUICK.
Be aware that InnoDB and MyISAM have their speed differences. One read faster, other writes faster ( read more about that on the internet )
disable stopword for fulltext search in mysql using this steps
1: open my.ini file in mysql
2: place below two line after [mysqld] line in my.ini (search [mysqld] in file)
ft_min_word_len=1
ft_stopword_file=""
3: restart your server
4: repair your table using below command
> repair table tablename;
5: now your search is working....
For the INNODB case, it is possible to disable stop_words when you create the index.
SET ##SESSION.innodb_ft_enable_stopword = 'OFF';
create table foo
....
fulltext (search_col)
This will cause the full text index to be created with the stopwords disabled. You can verify by using the following queries.
SET GLOBAL innodb_ft_aux_table = 'schema/foo';
select * from information_schema.innodb_ft_config;
Your results will look like this:
Notice that use_stopword is set to 0.
Search for use_stopwords on this mysql documentation page.
and Checkout innodb_ft_enable_stopword here
setting
ft_stopword_file = ""
didn't work for me, I'm using INNODB tables and MySQL 5.6 (stop words still not indexed in full text indexes after optimizing associated table)
this solution works (even if you are not super user) :
CREATE TABLE mydb.stopwordslist(value VARCHAR(20)) ENGINE = INNODB;
INSERT INTO mydb.stopwordslist(value) VALUES ('skipthisword');
for all users but you still need super user rights :
SET GLOBAL innodb_ft_server_stopword_table = 'mydb/stopwordslist';
for just the user (assuming it the one who recreating indexes and updating columns)
SET SESSION innodb_ft_user_stopword_table = 'mydb/stopwordslist';
as it is a session variable, it won't last when your session is closed so please make sure you set it at each session or before you optimize or insert into tables having fulltext index or when you update column indexed by fulltext index
try using MATCH…AGAINST…IN BOOLEAN MODE
Like this one:
WHERE MATCH(author,title)
AGAINST('"origin of"' IN BOOLEAN MODE);