Hello. On Tue 2002-07-16 at 07:47:33 -0500, [EMAIL PROTECTED] wrote: > >> Of the data? Or of the queries? > > Not the data. Just your query, the output from explain and a create > > table statement. > > Query: > > SELECT DISTINCT cards_crypt.* > FROM user_haves, cards_crypt WHERE > cards_crypt.name LIKE "%harrod%" AND > user_haves.card_name = cards_crypt.name AND > user_haves.total_have > 0 AND > user_haves.user != "joe_bob_briggs" > > Explain: > > *************************** 1. row *************************** > table: user_haves > type: ALL > possible_keys: card_name,total_have > key: NULL > key_len: NULL > ref: NULL > rows: 79370 > Extra: where used; Using temporary > *************************** 2. row *************************** > table: cards_crypt > type: eq_ref > possible_keys: name > key: name > key_len: 255 > ref: user_haves.card_name > rows: 1 > Extra: where used > 2 rows in set (0.00 sec)
This tells, that for the first table no index can be used, but all rows have to be read in. And that for each row, one row of the second table is read, using the index "name", which has a length of 255 chars. Reading only one row is good, an index having 255 chars is bad. The first table has to be read completely, because the beginning "%" in "%harrod%" prevents the use of any kex (see http://www.mysql.com/doc/M/y/MySQL_indexes.html). I suggest to try the following, in the listed order, until you are satisfied with the speed: - Use the numeric primary key to join the tables, i.e. replace user_haves.card_name with a user_haves.card_num, which refers to cards_crypt.record_num and then change the where clause accordingly SELECT DISTINCT cards_crypt.* FROM user_haves, cards_crypt WHERE cards_crypt.name LIKE "%harrod%" AND user_haves.card_num = cards_crypt.record_num AND user_haves.total_have > 0 AND user_haves.user != "joe_bob_briggs" The will have the additional effect of making user_have smaller and more normalized. - If possible and reasonable for your application, create an FULLTEXT index over the card names and use its boolean(!) search instead of LIKE. The SELECT would look like (from mind): SELECT DISTINCT cards_crypt.* FROM user_haves, cards_crypt WHERE MATCH(cards_crypt.name) AGAINST ("+harrod" IN BOOLEAN MODE) AND user_haves.card_num = cards_crypt.record_num AND user_haves.total_have > 0 AND user_haves.user != "joe_bob_briggs" - Alternatively, if using FULLTEXT indexes is not feasable, split up cards_crypt.name into words (like "harrod"), create a seperate table with these words and a second table which assigns the words to card names, i.e. CREATE TABLE card_words ( record_num int unsigned NOT NULL auto_increment PRIMARY KEY, word varchar(255), UNIQUE word (word) ); CREATE TABLE words_to_cards ( word_num int unsigned NOT NULL, card_num int unsigned NOT NULL, PRIMARY KEY (word_num, card_num) ); Then the SELECT would look like SELECT DISTINCT cards_crypt.* FROM user_haves, cards_crypt, card_words, words_to_cards WHERE card_words.word = "harrod" AND words_to_cards.word_num = card_words.record_num AND cards_crypt.record_num = words_to_cards.card_num AND user_haves.card_num = cards_crypt.record_num AND user_haves.total_have > 0 AND user_haves.user != "joe_bob_briggs" Greetings, Benjamin. [...] > CREATE TABLE user_haves ( > card_name varchar(100) NOT NULL default '', > total_have int(11) unsigned NOT NULL default '0', > user varchar(50) NOT NULL default '', > available int(11) unsigned NOT NULL default '0', > record_num int(11) unsigned NOT NULL auto_increment, > PRIMARY KEY (record_num), > KEY user (user), > KEY card_name (card_name), > KEY total_have (total_have), > KEY available (available) > ) TYPE=ISAM PACK_KEYS=1; > > > CREATE TABLE cards_crypt ( > record_num int(11) unsigned NOT NULL auto_increment, > name varchar(255) NOT NULL default '', > clan varchar(100) NOT NULL default '', > capacity int(10) NOT NULL default '0', > disciplines varchar(100) default '', > superior varchar(100) default '', > inferior varchar(100) default '', > title varchar(100) default '', > bonus_penalty text, > release_set varchar(100) NOT NULL default '', > rarity varchar(50) default '', > artist varchar(100) default '', > have int(10) default '0', > need int(10) default '0', > notes text, > alternate_name varchar(255) default '', > card_monger_url varchar(255) default '', > PRIMARY KEY (record_num), > UNIQUE KEY name (name), > KEY clan (clan), > KEY capacity (capacity), > KEY release_set (release_set) > ) TYPE=ISAM PACK_KEYS=1; > -- [EMAIL PROTECTED] --------------------------------------------------------------------- Before posting, please check: http://www.mysql.com/manual.php (the manual) http://lists.mysql.com/ (the list archive) To request this thread, e-mail <[EMAIL PROTECTED]> To unsubscribe, e-mail <[EMAIL PROTECTED]> Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php