Mysql query optimization - its really slow - mysql

I have next log.
Please somebody explain me where is the problem.
My table deals is 142906 why is it taking so much time?
# Query_time: 5.524629 Lock_time: 0.000059 Rows_sent: 3 Rows_examined: 142906
SET timestamp=1381963341;
SELECT *,1 as distance FROM deals
WHERE end_date > '1381959736'
GROUP BY title
ORDER BY COALESCE(distance, 999999999) , distance ASC LIMIT 0 , 3;
Here is ddl.
CREATE TABLE `deals` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sku` varchar(180) NOT NULL DEFAULT '',
`price` decimal(8,2) DEFAULT NULL,
`retail_price` decimal(8,2) DEFAULT NULL,
`category` int(1) DEFAULT '4',
`advertiser` varchar(120) DEFAULT NULL,
`image_url` varchar(255) DEFAULT NULL,
`tiks` int(5) DEFAULT NULL,
`buy_url` varchar(255) DEFAULT NULL,
`description` text,
`views` int(6) NOT NULL DEFAULT '1',
`title` varchar(100) DEFAULT NULL,
`brand` varchar(100) DEFAULT NULL,
`api` varchar(50) DEFAULT NULL,
`discount` int(2) DEFAULT NULL,
`black_list` smallint(1) DEFAULT '0',
`gender` tinyint(1) DEFAULT NULL,
`sort` tinyint(1) DEFAULT NULL,
`is_home` tinyint(1) DEFAULT NULL,
`is_quick_shop` tinyint(1) DEFAULT NULL,
`date_add` int(11) DEFAULT NULL,
`is_sale` tinyint(1) DEFAULT NULL,
`is_new` tinyint(1) DEFAULT NULL,
`is_brand_show` tinyint(1) DEFAULT NULL,
`date_modified` int(11) NOT NULL DEFAULT '0',
`modifier_id` smallint(2) DEFAULT NULL,
`modified` smallint(1) DEFAULT NULL,
`longitute` decimal(10,8) DEFAULT NULL,
`latitute` decimal(10,8) DEFAULT NULL,
`is_deal` tinyint(1) DEFAULT NULL,
`best_seller` tinyint(1) DEFAULT NULL,
`home_cat` int(2) DEFAULT NULL,
`end_date` int(11) DEFAULT NULL,
`temp_category` varchar(120) DEFAULT NULL,
`update_cron` smallint(1) unsigned DEFAULT '1',
`alias` varchar(120) DEFAULT NULL,
`found_by` text,
`fb_share` smallint(3) DEFAULT NULL,
`tw_share` smallint(3) DEFAULT NULL,
`pin_share` smallint(3) DEFAULT NULL,
`google_share` smallint(3) DEFAULT NULL,
`last_tiked` int(11) DEFAULT NULL,
`is_simple` smallint(1) DEFAULT '0',
`dealer_id` int(3) DEFAULT NULL,
`clicks` int(5) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `sku` (`sku`),
KEY `tiks` (`tiks`),
KEY `category` (`category`),
KEY `bests` (`best_seller`),
KEY `ne` (`is_new`),
KEY `qu` (`is_quick_shop`),
KEY `end_date` (`end_date`),
KEY `lat` (`latitute`),
KEY `lon` (`longitute`),
KEY `alias` (`alias`),
FULLTEXT KEY `title` (`title`),
FULLTEXT KEY `desc` (`description`),
FULLTEXT KEY `brand` (`brand`),
FULLTEXT KEY `advertiser` (`advertiser`),
FULLTEXT KEY `found_by` (`found_by`)
) ENGINE=MyISAM AUTO_INCREMENT=1861942 DEFAULT CHARSET=utf8

Assuming end_date is a date, convert the number into a date type using FROM_UNIXTIME()
SELECT *, 1 as distance
FROM deals
WHERE end_date > FROM_UNIXTIME(1381959736)
GROUP BY title
ORDER BY COALESCE(distance, 999999999), distance ASC
LIMIT 0, 3;
That way mysql doesn't have the cast every row's end_date to a string, which is very slow. It can also use an index if one exists, so make sure you have one:
create index deals_end_date on deals(end_date);

Related

mysql 'slow queries log' return a huge number of rows examined but explain seems ok

The sql query
# Query_time: 16.536276 Lock_time: 0.000159 Rows_sent: 756 Rows_examined: 8392194
SET timestamp=1555422526;
SELECT c.id AS c__id, c.company_id AS c__company_id,
c.ordinary_price AS c__ordinary_price, c.nights AS c__nights,
c.food_type AS c__food_type, c.period AS c__period,
c.period_desc AS c__period_desc, c.extra AS c__extra,
c.coupons_bought AS c__coupons_bought, c.coupon_price AS c__coupon_price,
c.coordinates AS c__coordinates, c.best_price AS c__best_price,
c.from_price AS c__from_price, c.end_datetime AS c__end_datetime,
c.hide_clock AS c__hide_clock, c.hide_discount AS c__hide_discount,
c.booking_hotel_id AS c__booking_hotel_id, c.title AS c__title,
c.option_people AS c__option_people, c.option_room AS c__option_room,
c.option_period AS c__option_period, c.city AS c__city,
c2.id AS c2__id, c2.people AS c2__people, c2.room AS c2__room,
( SELECT c8.url AS c8__url
FROM campaign_images c8
WHERE (c8.campaign_id = c.id
AND c8.photo_type = 'list')
ORDER BY c8.ordering ASC LIMIT 1
) AS c__0
FROM campaign c
LEFT JOIN campaign_options c2 ON c.id = c2.campaign_id
AND (c2.active = 1)
LEFT JOIN city_in_campaign c3 ON c.id = c3.campaign_id
LEFT JOIN city c4 ON c3.city_id = c4.id
LEFT JOIN company c5 ON c.company_id = c5.id
LEFT JOIN campaign_in_category c6 ON c.id = c6.campaign_id
LEFT JOIN campaign_in_group c7 ON c.id = c7.campaign_id
WHERE c.id IN ('13308', '13281', '13265')
AND (c.status IN ('published')
AND c.start_datetime <= NOW()
AND c.end_datetime >= NOW()
AND c5.id = '2111'
AND c.id != '14624'
AND (c7.group_id in (1)
OR c7.group_id is NULL
)
)
ORDER BY c.coupon_expire_datetime ASC;
create table campaign
CREATE TABLE `campaign` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`company_id` int(11) DEFAULT NULL,
`source_id` int(11) DEFAULT NULL,
`secondary_source_id` int(11) DEFAULT NULL,
`source_hotel_id` int(11) DEFAULT NULL,
`booking_hotel_id` int(11) DEFAULT NULL,
`booking_board_id` int(11) DEFAULT NULL,
`booking_rate` varchar(100) DEFAULT NULL,
`ordinary_price` decimal(9,2) NOT NULL,
`best_price` tinyint(1) NOT NULL DEFAULT '0',
`from_price` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(10) DEFAULT 'draft',
`type` varchar(20) DEFAULT 'other',
`deal_status` varchar(20) DEFAULT 'in_progress',
`coupon_price` decimal(9,2) NOT NULL,
`cosmote_discount` decimal(5,2) DEFAULT NULL,
`nights` int(11) NOT NULL DEFAULT '0',
`period` varchar(255) DEFAULT NULL,
`period_desc` varchar(1000) DEFAULT NULL,
`hide_period` tinyint(1) NOT NULL DEFAULT '0',
`food_type` varchar(100) DEFAULT NULL,
`stars` varchar(100) DEFAULT NULL,
`adults` tinyint(1) DEFAULT NULL,
`childs` tinyint(1) DEFAULT NULL,
`extra` varchar(255) DEFAULT NULL,
`best_point` varchar(511) DEFAULT NULL,
`extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`high_season_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`high_season_desc` varchar(500) DEFAULT NULL,
`high_season_extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`family_packages_desc` varchar(1000) DEFAULT NULL,
`coordinates` varchar(70) DEFAULT NULL,
`start_datetime` datetime DEFAULT NULL,
`end_datetime` datetime DEFAULT NULL,
`coupon_expire_datetime` datetime DEFAULT NULL,
`active` tinyint(4) NOT NULL DEFAULT '1',
`city` varchar(255) DEFAULT NULL,
`min_coupons` int(11) NOT NULL DEFAULT '0',
`is_global` tinyint(4) NOT NULL DEFAULT '0',
`hide_clock` tinyint(1) NOT NULL DEFAULT '0',
`hide_discount` tinyint(1) NOT NULL DEFAULT '0',
`hide_purchases` tinyint(1) NOT NULL DEFAULT '0',
`booking_enabled` tinyint(1) NOT NULL DEFAULT '0',
`booking_phone` varchar(50) DEFAULT NULL,
`refresh` tinyint(1) NOT NULL DEFAULT '0',
`installments` tinyint(1) NOT NULL DEFAULT '1',
`receipt` enum('0','1') NOT NULL DEFAULT '0',
`newsletters_sent` tinyint(4) NOT NULL DEFAULT '0',
`max_coupons` int(11) NOT NULL DEFAULT '0',
`max_coupons_per_user` int(11) DEFAULT NULL,
`coupons_bought` int(11) unsigned NOT NULL DEFAULT '0',
`fake_orders` int(11) DEFAULT '0',
`title` varchar(255) DEFAULT NULL,
`newsletter_title` varchar(500) DEFAULT NULL,
`linkwise_title` varchar(500) DEFAULT NULL,
`option_title` varchar(255) DEFAULT NULL,
`option_title_en` varchar(255) DEFAULT NULL,
`option_people` varchar(150) DEFAULT NULL,
`option_room` varchar(150) DEFAULT NULL,
`option_period` varchar(150) DEFAULT NULL,
`name` varchar(1200) DEFAULT NULL,
`description` text,
`highlights` text,
`coupon_instructions` text,
`show_in_recent_deals` tinyint(4) NOT NULL DEFAULT '1',
`youtube_video_id` varchar(100) DEFAULT NULL,
`in_side` tinyint(4) NOT NULL DEFAULT '0',
`family` tinyint(1) NOT NULL DEFAULT '0',
`send_newsletter` tinyint(4) NOT NULL DEFAULT '1',
`resend_newsletter` tinyint(4) NOT NULL DEFAULT '0',
`modified_datetime` timestamp NULL DEFAULT NULL,
`created_datetime` datetime NOT NULL,
`ordering` int(11) unsigned DEFAULT '0',
PRIMARY KEY (`id`),
KEY `company_id_idx` (`company_id`),
KEY `user_id_idx` (`user_id`),
KEY `status_indx` (`status`),
KEY `str_dt_indx` (`start_datetime`),
KEY `end_dt_indx` (`end_datetime`),
KEY `side_indx` (`in_side`),
KEY `ord_indx` (`ordering`),
KEY `global_indx` (`is_global`),
KEY `act_indx` (`active`),
KEY `coup_expr_index` (`coupon_expire_datetime`)
) ENGINE=InnoDB AUTO_INCREMENT=14788 DEFAULT CHARSET=utf8
create table campaign_options
CREATE TABLE `campaign_options` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`coupons_bought` int(11) unsigned NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`name_en` varchar(255) DEFAULT NULL,
`people` varchar(100) DEFAULT NULL,
`room` varchar(100) DEFAULT NULL,
`food` varchar(100) DEFAULT NULL,
`period` varchar(100) DEFAULT NULL,
`coupon_price` decimal(9,2) NOT NULL,
`extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`high_season_price` decimal(9,2) DEFAULT '0.00',
`high_season_extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`modified_datetime` timestamp NULL DEFAULT NULL,
`created_datetime` datetime NOT NULL,
`main` tinyint(1) NOT NULL DEFAULT '0',
`family` tinyint(1) NOT NULL DEFAULT '0',
`active` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `campaign_id_idx` (`campaign_id`),
KEY `active_indx` (`active`),
KEY `family_indx` (`family`),
KEY `main_indx` (`main`)
) ENGINE=InnoDB AUTO_INCREMENT=48990 DEFAULT CHARSET=utf8
create table city_in_campaign
CREATE TABLE `city_in_campaign` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) DEFAULT NULL,
`city_id` int(11) DEFAULT NULL,
`ordering` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `campaign_id_idx` (`campaign_id`),
KEY `city_id_idx` (`city_id`),
KEY `order_indx` (`ordering`)
) ENGINE=InnoDB AUTO_INCREMENT=227176 DEFAULT CHARSET=utf8
create table city
CREATE TABLE `city` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`country_id` int(11) DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
`is_active` tinyint(3) unsigned DEFAULT NULL,
`modified_datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `country_id_idx` (`country_id`),
KEY `is_active_indx` (`is_active`)
) ENGINE=InnoDB AUTO_INCREMENT=254 DEFAULT CHARSET=utf8
create table company
CREATE TABLE `company` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`ref_id` int(11) DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
`description` text,
`logo` varchar(255) DEFAULT NULL,
`phone_number` varchar(100) DEFAULT NULL,
`address` varchar(200) DEFAULT NULL,
`coordinates` varchar(70) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`website` varchar(255) DEFAULT NULL,
`skype_name` varchar(50) DEFAULT NULL,
`icq_number` varchar(255) DEFAULT NULL,
`payment_information` text,
`extra1` text,
`extra2` text,
`extra3` text,
`video` varchar(500) DEFAULT NULL,
`checked` tinyint(1) NOT NULL DEFAULT '0',
`ordering` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `checked_indx` (`checked`),
KEY `ordering_indx` (`ordering`)
) ENGINE=InnoDB AUTO_INCREMENT=2519 DEFAULT CHARSET=utf8
create table campaign_in_category
CREATE TABLE `campaign_in_category` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`category_id` int(11) DEFAULT NULL,
`ordering` int(11) NOT NULL DEFAULT '0',
`created_datetime` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `campaign_id_idx` (`campaign_id`),
KEY `category_id_idx` (`category_id`),
KEY `order_indx` (`ordering`)
) ENGINE=InnoDB AUTO_INCREMENT=457080 DEFAULT CHARSET=utf8
create table campaign_in_group
CREATE TABLE `campaign_in_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) DEFAULT NULL,
`group_id` int(11) DEFAULT NULL,
`created_datetime` datetime DEFAULT NULL,
`modified_datetime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `camp_group_indx` (`campaign_id`,`group_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1175 DEFAULT CHARSET=utf8
campaign total rows: 12,657
campaign_options total rows: 43,714
city_in_campaign total rows: 15,162
city total rows: 215
company total rows: 1,756
campaign_in_category total rows: 38,817
campaign_in_group total rows: 395
explain of the query
which ones have index
it looks you need composite index because file sorting.
usage:
CREATE INDEX index_name
ON table_name(c2,c3,c4);
You are getting above result because some time o/p of explain gives different result as response of query of prod.
For optimization of query you can't have a fix answer. it varies from case to case. As for this situation I think you need to perform performance testing of this query. You can do this by inserting some records in all referenced table and then checking it's performance using explain.
LEFT JOIN campaign_in_category c6 ON c.id = c6.campaign_id
seems to be totally useless. But the Optimizer may not realize it. Remove it and any other dead code.

Multi column searching

I have real estate website. Currently my table looks like this
CREATE TABLE `properties` (
`property_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`property_type` int(11) NOT NULL,
`seller_id` int(11) NOT NULL,
`seller_type` int(11) NOT NULL,
`transaction_type` tinyint(4) NOT NULL DEFAULT '1',
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`price` int(10) unsigned NOT NULL,
`area` int(11) NOT NULL,
`bedrooms` tinyint(4) NOT NULL,
`bathrooms` tinyint(4) NOT NULL,
`city` varchar(30) NOT NULL,
`location` varchar(30) NOT NULL,
`listing_images` text NOT NULL,
`list_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`activated` tinyint(4) NOT NULL DEFAULT '0',
`property_status` tinyint(4) NOT NULL DEFAULT '0',
`reviewed` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`property_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
In the search properties page, there is a form that allows users to filter by property type,seller type, maximum price, area, max & min bedrooms,bathrooms etc to narrow it. I tried to optimize it by creating index on each field, but it is very slow. What is the correct way to optimize this?

Two MySql tables have correct indexes yet JOIN takes 9 seconds on small tables

mysql Ver 14.14 Distrib 5.1.73, for redhat-linux-gnu (x86_64) using readline 5.1
I am taking over a project. It is very old and the original programmer is long gone. No one has any idea why certain decisions were made.
The following query runs (on my Mac) in 9.5 seconds but if I remove the last JOIN then it drops to 2.5 seconds. What is wrong with that last JOIN?
select `ttl`.`id` AS `id`,
`ttl`.`name` AS `name`,
`ttl`.`updated_at` AS `last_update_on`,
`ttl`.`user_id` AS `list_creator`,
`ttl`.`retailer_nomination_list` AS `nomination_list`,
`ttl`.`created_at` AS `created_on`,
count(distinct `tlb`.`title_id`) AS `title_count`
from `haha_title_lists` `ttl`
left join `haha_title_list_to_users` `tltu` on((`ttl`.`id` = `tltu`.`title_list_id`))
left join `users` `u` on((`tltu`.`user_id` = `u`.`id`))
left join `users` `u2` on((`tltu`.`user_id` = `u2`.`id`))
left join `haha_title_list_to_venues` `tlv` on((`ttl`.`id` = `tlv`.`title_list`))
left join `haha_venue_properties` `tvp` on((`tlv`.`venue_id` = `tvp`.`id`))
join `haha_title_list_to_books` `tlb` on((`ttl`.`id` = `tlb`.`title_list_id`))
join `wawa_title` `ot` on((`tlb`.`title_id` = `ot`.`title_id`))
group by `ttl`.`id`;
The tables:
CREATE TABLE `haha_title_list_to_books` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title_id` int(11) NOT NULL,
`title_list_id` int(11) NOT NULL,
`sdk` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`created_at` datetime NOT NULL,
`promo_start_date` date DEFAULT NULL,
`promo_end_date` date DEFAULT NULL,
`promo_price` float DEFAULT NULL,
`confirmations` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`nominations` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`title_note` text COLLATE utf8_unicode_ci,
`executed` int(11) DEFAULT NULL,
`event_created` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_promo_start_date` (`promo_start_date`),
KEY `idx_promo_end_date` (`promo_end_date`),
KEY `idx_title_list_to_books_title_id` (`title_id`),
KEY `idx_title_list_to_books_title_list_id` (`title_list_id`)
) ENGINE=MyISAM AUTO_INCREMENT=21847 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
and:
CREATE TABLE `wawa_title` (
`title_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(200) DEFAULT NULL,
`title_alpha` varchar(25) NOT NULL,
`display_title` varchar(200) NOT NULL,
`subtitle` text NOT NULL,
`sdk10` varchar(13) DEFAULT '',
`sdk13` varchar(15) DEFAULT NULL,
`primary_sdk13` varchar(15) DEFAULT NULL,
`asin` varchar(10) DEFAULT NULL,
`pub_season` varchar(15) NOT NULL,
`pub_year` varchar(15) NOT NULL,
`bisac1` varchar(15) NOT NULL,
`bisac2` varchar(15) NOT NULL,
`bisac3` varchar(15) NOT NULL,
`barcode` varchar(30) DEFAULT NULL,
`dewey_decimal` varchar(15) NOT NULL,
`lib_of_congress` varchar(15) NOT NULL,
`spanish_language` tinyint(4) NOT NULL,
`target_audience` tinyint(3) unsigned DEFAULT NULL,
`language` varchar(20) DEFAULT NULL,
`edition` varchar(45) DEFAULT NULL,
`pages` int(11) DEFAULT NULL,
`number_in_series` int(11) DEFAULT NULL,
`trimsize` varchar(10) DEFAULT NULL,
`filesize` varchar(10) DEFAULT NULL,
`duration_hours` int(11) DEFAULT NULL,
`duration_minutes` int(11) DEFAULT NULL,
`discs` int(11) DEFAULT NULL,
`download` date DEFAULT NULL,
`size_unit` varchar(15) NOT NULL DEFAULT '',
`digitization_date` date NOT NULL,
`us_on_sale_date` date NOT NULL,
`aus_on_sale_date` date NOT NULL,
`can_on_sale_date` date NOT NULL,
`uk_on_sale_date` date NOT NULL,
`us_list_price` varchar(10) NOT NULL,
`aus_list_price` varchar(10) NOT NULL,
`can_list_price` varchar(10) NOT NULL,
`uk_list_price` varchar(10) NOT NULL,
`isPrimary` varchar(1) DEFAULT NULL,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modifier` int(11) NOT NULL,
`activated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` varchar(3) NOT NULL DEFAULT 'N',
`flagged_string` text,
`created` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`assets_id` varchar(20) DEFAULT NULL,
`book_details` text,
`book_keynote` text,
`exclude_goodreads` char(1) NOT NULL DEFAULT 'N',
`series_description` text,
`review_quote1` text,
`territory_id` int(11) DEFAULT '27',
`featured_newsletter_id` tinyint(3) unsigned DEFAULT '0',
`retailer_discovery_check` datetime DEFAULT NULL,
`suppress_retailer_approval` tinyint(1) DEFAULT '0',
`suppress_retailer_approval_reason` varchar(255) DEFAULT NULL,
`ebb_description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`slug` varchar(150) DEFAULT NULL,
`legacy_slug` varchar(150) DEFAULT NULL,
`us_agency_price` varchar(10) DEFAULT NULL,
`firebrand_title_id` int(11) DEFAULT NULL,
`ebb_label` varchar(200) DEFAULT NULL,
`ebb_end_sale_date` date DEFAULT NULL,
`ebb_downprice` decimal(10,2) DEFAULT NULL,
`book_club` varchar(1) DEFAULT NULL,
`best_seller` varchar(1) DEFAULT NULL,
`award_winner` varchar(1) DEFAULT NULL,
`discovery` char(1) NOT NULL DEFAULT 'Y',
`narrator_id` int(11) DEFAULT NULL,
`suppress_series_data` varchar(255) DEFAULT NULL,
PRIMARY KEY (`title_id`),
KEY `active_index` (`active`),
KEY `fk_title_series_id_idx` (`series_id`),
KEY `series_id` (`series_id`),
KEY `idx_title_sdk13` (`sdk13`),
KEY `idx_title_active_isprimary` (`active`,`isPrimary`),
KEY `bisac1` (`bisac1`),
KEY `bisac2` (`bisac2`),
KEY `bisac3` (`bisac3`),
KEY `idx_primary_sdk13` (`primary_sdk13`),
KEY `idx_territory_id` (`territory_id`),
CONSTRAINT `fk_title_series_id` FOREIGN KEY (`series_id`) REFERENCES `wawa_series` (`series_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=19700 DEFAULT CHARSET=utf8 |
If I remove this line:
join `wawa_title` `ot` on((`tlb`.`title_id` = `ot`.`title_id`))
The query speed drops from 9.5 seconds to 2.5 seconds. Not great, but a huge improvement.
And yet, both tables have indexes on table_id, so why would that line be a problem?
I notice that one table is InnoDB and the other is MyISAM. Would that have an effect?
Do not JOIN to tables that you don't use.
A JOIN often "explodes" the number of rows, then a GROUP BY like you have reels in the number of rows. To see this, leave all the JOINs there, but remove the GROUP BY. See how many rows you get.
To avoid part of that explosion, change
count(distinct `tlb`.`title_id`) AS `title_count`
to
( SELECT count(distinct `title_id`)
FROM `haha_title_list_to_books`
WHERE `ttl`.`id` = `title_list_id`
) AS `title_count`
and remove the current JOIN to tlb.
Mixing MyISAM and InnoDB should not have any direct impact on this SELECT. However, you should consider moving all of your tables to InnoDB.

Cardinality of an index in a MySQL table is equal to table's row size

I have just included an index to a MyISAM table and the cardinality appears to be 1 million something which is exactly the number of rows in the table. In fact it needed to be 315 because distinct count returns 315. And then I have realized that there are 3 other such indexes (equal to tables's row size), and all their distinct counts are way below. So, what could be the reason these indexes' carnalities are equal to table's row size?
Note: There are 97 columns and 27 indexes.
The table:
CREATE TABLE `isemri` (
`RECNO` int(12) NOT NULL AUTO_INCREMENT,
`MUSTERI_RECNO` int(11) NOT NULL,
`MUSTERI_PER_RECNO` int(11) DEFAULT NULL,
`YIL` smallint(4) unsigned zerofill NOT NULL DEFAULT '0000',
`ISEMRI_NO` int(6) NOT NULL DEFAULT '0',
`BOLGE` int(6) unsigned NOT NULL,
`URUN_BARKOD` varchar(13) NOT NULL DEFAULT '''''',
`ISTEK_TIPI` tinyint(1) DEFAULT '0',
`MUSTERI_NO` bigint(20) DEFAULT NULL,
`SERVIS_CAGRI_TAR` datetime DEFAULT NULL,
`MUSTERI_PER` varchar(30) DEFAULT NULL,
`SERVIS_BAS_TAR` datetime DEFAULT NULL,
`SERVIS_BIT_TAR` datetime DEFAULT NULL,
`ISTEGI_ALAN` varchar(15) DEFAULT NULL,
`URUN_CIHAZ` smallint(6) DEFAULT NULL,
`URUN_CIHAZ_ADI` varchar(40) DEFAULT NULL,
`URUN_MARKA` smallint(6) DEFAULT NULL,
`URUN_MARKA_ADI` varchar(20) DEFAULT NULL,
`URUN_MODEL` varchar(35) DEFAULT NULL,
`URUN_MODEL_ADI` varchar(150) DEFAULT NULL,
`URUN_SERI_NO` varchar(100) DEFAULT NULL,
`SERVIS_VEREN` varchar(50) DEFAULT NULL,
`SERVIS_TURU` tinyint(2) NOT NULL DEFAULT '1',
`ARIZA_ACIKLAMASI` mediumtext,
`ARIZASERVIS_ACIKLAMA` varchar(250) DEFAULT NULL,
`ACILIYET_DERECESI` tinyint(2) NOT NULL DEFAULT '2',
`SERVIS_DURUMU` tinyint(2) NOT NULL DEFAULT '1',
`GERI_BILDIRIM` tinyint(1) NOT NULL DEFAULT '0',
`KON_GEL_DON_TAR` datetime DEFAULT NULL,
`GERI_BILDIRIM_TARIHI` datetime DEFAULT NULL,
`TAHMINI_TESLIM_TARIHI` datetime DEFAULT NULL,
`YAPILANLAR` varchar(255) DEFAULT NULL,
`YAPILANLAR_M` mediumtext,
`SERVIS_YERI` varchar(20) DEFAULT NULL,
`TOPLAM` float(12,2) DEFAULT NULL,
`KDV_TOP` float(12,2) DEFAULT NULL,
`GENEL_TOPLAM` float(12,2) DEFAULT NULL,
`INSERT_USER` varchar(15) DEFAULT NULL,
`GIRIS_KARGO_NO` varchar(10) DEFAULT NULL,
`INSERT_DATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`UPDATE_USER` varchar(10) DEFAULT NULL,
`UPDATE_DATE` datetime DEFAULT NULL,
`BARKOD` int(6) NOT NULL DEFAULT '0',
`SERVIS_BITIS` tinyint(1) DEFAULT '0',
`GARANTI_BELGENO` varchar(12) DEFAULT NULL,
`GARANTI_TARIHI` date DEFAULT NULL,
`EL_ISEMRI_NO` int(11) DEFAULT '0',
`ONAY_TARIHI` datetime DEFAULT NULL,
`ONAYLAYAN` varchar(30) DEFAULT NULL,
`ALAN1` varchar(20) DEFAULT NULL,
`ALAN2` varchar(20) DEFAULT NULL,
`ALAN3` varchar(20) DEFAULT NULL,
`ALAN4` varchar(20) DEFAULT NULL,
`DOLAR_KURU` float DEFAULT '2',
`EURO_KURU` float DEFAULT '2',
`KDV` tinyint(1) DEFAULT '0',
`BILGILENDIR` tinyint(1) DEFAULT '0',
`TESLIM_SEKLI` varchar(10) DEFAULT NULL,
`TESLIM_NOTU` varchar(150) DEFAULT NULL,
`ARIZA_TIP_NO` smallint(6) DEFAULT NULL,
`ARIZASERVIS_TIP` smallint(6) DEFAULT NULL,
`GETIREN_KARGO_FRM` varchar(50) DEFAULT NULL,
`SERV_ALAN1` varchar(25) DEFAULT NULL,
`SERV_ALAN2` varchar(25) DEFAULT NULL,
`DOSYA__` varchar(250) DEFAULT NULL,
`HAKEDIS_DURUM` tinyint(1) unsigned DEFAULT '0',
`HAKEDIS_FATURANO` int(11) DEFAULT NULL,
`HAKEDIS_FATURA_DURUM` int(1) DEFAULT '0',
`ONAY_DURUM` tinyint(1) unsigned DEFAULT '0',
`MONTAJ_KODU` int(6) DEFAULT NULL,
`urun_id` int(11) DEFAULT NULL,
`gondKargoFirmasi` tinyint(2) DEFAULT NULL,
`gondKargoNo` int(11) DEFAULT NULL,
`gondIrsNo` varchar(30) DEFAULT NULL,
`gondGelTar` date DEFAULT NULL,
`BAYI_KODU` varchar(50) DEFAULT '0',
`HAKEDIS_TARIHI` datetime DEFAULT NULL,
`HAKEDIS_ONAY_PERSONEL` varchar(30) DEFAULT NULL,
`HURDA_CTRL` tinyint(2) DEFAULT '0',
`DOSYA` tinyint(2) DEFAULT '0',
`RANDEVU_TARIHI` datetime DEFAULT NULL,
`MUSTERI_ACIKLAMA` varchar(200) DEFAULT NULL,
`PLASIYER` varchar(50) DEFAULT NULL,
`FIRMA_SERINO` varchar(20) DEFAULT NULL,
`MONTAJ_KART_NO` varchar(50) DEFAULT NULL,
`SERINO2` varchar(50) DEFAULT NULL,
`SATICI_FIRMA` varchar(50) DEFAULT NULL,
`URUN_DEGISIM_DURUMU` int(11) DEFAULT NULL,
`URUN_HASAR_DURUMU` int(6) DEFAULT NULL,
`BOLGE_2` varchar(12) DEFAULT NULL,
`KILIT` int(2) DEFAULT NULL,
`ON_ONAY` int(11) DEFAULT NULL,
`RANDEVU_BITIS_TARIHI` datetime DEFAULT NULL COMMENT 'iş emri randavü bitiş tarihi',
`URUN_KALITE` tinyint(4) DEFAULT NULL,
`BOLGE_X` varchar(255) DEFAULT NULL,
`REWORK` enum('0','1') DEFAULT '0' COMMENT 'Rework olup olmadığını gösteriyor.',
PRIMARY KEY (`RECNO`),
KEY `MUSTERI_NO` (`MUSTERI_NO`) USING BTREE,
KEY `EL_ISEMRI_NO` (`EL_ISEMRI_NO`) USING BTREE,
KEY `MUSTERI_RECNO` (`MUSTERI_RECNO`) USING BTREE,
KEY `ISEMRI_NO` (`ISEMRI_NO`) USING BTREE,
KEY `ALAN1` (`ALAN1`) USING BTREE,
KEY `URUN_SERI_NO` (`URUN_SERI_NO`) USING BTREE,
KEY `SERVIS_TURU` (`SERVIS_TURU`) USING BTREE,
KEY `SERVIS_DURUMU` (`SERVIS_DURUMU`) USING BTREE,
KEY `ISTEK_TIPI` (`ISTEK_TIPI`) USING BTREE,
KEY `urun_id` (`urun_id`) USING BTREE,
KEY `URUN_CIHAZ` (`URUN_CIHAZ`) USING BTREE,
KEY `HAKEDIS_DURUM` (`HAKEDIS_DURUM`) USING BTREE,
KEY `HAKEDIS_TARIHI` (`HAKEDIS_TARIHI`) USING BTREE,
KEY `HAKEDIS_ONAY_PERSONEL` (`HAKEDIS_ONAY_PERSONEL`) USING BTREE,
KEY `SERVIS_BAS_TAR` (`SERVIS_BAS_TAR`) USING BTREE,
KEY `BOLGE_2` (`BOLGE_2`) USING BTREE,
KEY `URUN_MARKA` (`URUN_MARKA`) USING BTREE,
KEY `URUN_MODEL` (`URUN_MODEL`) USING BTREE,
KEY `MUSTERI_PER` (`MUSTERI_PER`) USING BTREE,
KEY `MONTAJ_KODU` (`MONTAJ_KODU`) USING BTREE,
KEY `BOLGE` (`BOLGE`),
KEY `HAKEDIS_FATURANO` (`HAKEDIS_FATURANO`),
KEY `REWORK` (`REWORK`) USING BTREE,
KEY `SERVIS_BITIS` (`SERVIS_BITIS`) USING BTREE,
KEY `HAKEDIS_FATURA_DURUM` (`HAKEDIS_FATURA_DURUM`),
KEY `MUSTERI_PER_RECNO` (`MUSTERI_PER_RECNO`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1335476 DEFAULT CHARSET=utf8 PACK_KEYS=0 ROW_FORMAT=DYNAMIC
SHOW TABLE STATUS:
Name: isemri
Engine: MyISAM
Version: 10
Rpw_format: Dynamic
Rows: 1328150
Avg_row_length: 459
Data_length: 610624628
Max_data_length: 281474976710655
Index_length: 420404224
Data_free: 0
Auto_icrement: 1335384
Create_time: 2016-02-12 16:22:12
Update_time: 2016-02-13 10:43:59
Check_time: 2016-02-12 17:52:23
Collation: utf8_general_ci
Checksum:
Create_options: pack_keys=0 row_format=DYNAMIC
Comment:
Distinct count:
URUN_SERI_NO: 1012754
SERVIS_BAS_TAR: 1300066
BOLGE_2: 5
MUSTERI_PER_RECNO: 319

Indexes in Mysql table

I have such tables:
CREATE TABLE `skadate_newsfeed_action` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entityId` int(11) NOT NULL,
`entityType` varchar(100) NOT NULL,
`feature` varchar(100) NOT NULL,
`data` longtext NOT NULL,
`status` varchar(20) NOT NULL DEFAULT 'active',
`createTime` int(11) NOT NULL,
`updateTime` int(11) NOT NULL,
`userId` int(11) NOT NULL,
`visibility` int(11) NOT NULL,
`privacy` enum('everybody','friends_only') NOT NULL DEFAULT 'everybody',
PRIMARY KEY (`id`),
KEY `userId` (`userId`),
KEY `privacy` (`visibility`),
KEY `updateTime` (`updateTime`),
KEY `entity` (`entityType`,`entityId`)
) ENGINE=MyISAM;
CREATE TABLE `skadate_profile` (
`profile_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(128) NOT NULL DEFAULT '',
`username` varchar(32) NOT NULL DEFAULT '',
`password` varchar(40) NOT NULL,
`sex` bigint(20) DEFAULT NULL,
`match_sex` bigint(20) DEFAULT NULL,
`birthdate` date NOT NULL DEFAULT '0000-00-00',
`headline` varchar(128) DEFAULT '',
`general_description` text,
`match_agerange` varchar(6) DEFAULT NULL,
`custom_location` varchar(255) DEFAULT NULL,
`country_id` char(2) NOT NULL DEFAULT '',
`zip` varchar(10) DEFAULT NULL,
`state_id` varchar(5) DEFAULT NULL,
`city_id` int(11) DEFAULT '0',
`join_stamp` int(10) unsigned NOT NULL DEFAULT '0',
`activity_stamp` int(10) unsigned NOT NULL DEFAULT '0',
`membership_type_id` int(10) unsigned NOT NULL DEFAULT '18',
`affiliate_id` int(8) unsigned NOT NULL DEFAULT '0',
`email_verified` enum('undefined','yes','no') NOT NULL DEFAULT 'undefined',
`reviewed` enum('n','y') NOT NULL DEFAULT 'n',
`has_photo` enum('n','y') NOT NULL DEFAULT 'n',
`has_media` enum('n','y') NOT NULL DEFAULT 'n',
`status` enum('active','on_hold','suspended') NOT NULL DEFAULT 'active',
`featured` enum('n','y') NOT NULL DEFAULT 'n',
`register_invite_score` tinyint(3) NOT NULL DEFAULT '0',
`rate_score` tinyint(3) unsigned NOT NULL DEFAULT '0',
`rates` bigint(20) unsigned NOT NULL DEFAULT '0',
`language_id` int(10) unsigned NOT NULL DEFAULT '0',
`join_ip` int(11) unsigned NOT NULL DEFAULT '0',
`neigh_location` enum('country','state','city','zip') DEFAULT NULL,
`neigh_location_distance` int(10) unsigned NOT NULL DEFAULT '0',
`bg_color` varchar(32) DEFAULT NULL,
`bg_image` varchar(32) DEFAULT NULL,
`bg_image_url` varchar(255) DEFAULT NULL,
`bg_image_mode` tinyint(1) DEFAULT NULL,
`bg_image_status` enum('active','approval') NOT NULL DEFAULT 'active',
`has_music` enum('n','y') NOT NULL DEFAULT 'n',
`is_private` tinyint(1) NOT NULL DEFAULT '0',
`subscription_id_offerit` text,
PRIMARY KEY (`profile_id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `username` (`username`),
KEY `membership_id` (`membership_type_id`),
KEY `zip` (`zip`),
KEY `country_id` (`country_id`),
KEY `state_id` (`state_id`),
KEY `city_id` (`city_id`),
KEY `sex` (`sex`),
KEY `match_sex` (`match_sex`),
KEY `activity_stamp` (`activity_stamp`),
KEY `join_stamp` (`join_stamp`),
KEY `birthdate` (`birthdate`),
KEY `featured` (`featured`,`has_photo`,`activity_stamp`)
) ENGINE=MyISAM;
And try to perform this query:
SELECT DISTINCT `na`.*
FROM `skadate_newsfeed_action` AS `na`
LEFT JOIN `skadate_profile` AS `profile` ON ( `na`.`userId` = `profile`.`profile_id` )
WHERE ( profile.email_verified='yes' OR profile.email_verified='no' OR profile.email_verified='undefined' )
AND `profile`.`status`='active' AND `na`.`status`='active' AND `na`.`privacy`='everybody'
AND `na`.`visibility` & 1 AND `na`.`updateTime` < 1455885224
ORDER BY `na`.`updateTime` DESC, `na`.`id` DESC
LIMIT 0, 10
But when I see EXPLAIN:
Maybe someone can help me, how I can improve this query?
If you want records from only one table, then use exists rather than a join and select distinct. So:
SELECT na.*
FROM `skadate_newsfeed_action` na
WHERE EXISTS (SELECT 1
FROM skadate_profile p
WHERE na.userId = p.profile_id AND
p.email_verified IN ('yes', 'no', 'undefined') AND
p.status = 'active'
) AND
na.status = 'active' AND
na.privacy = 'everybody' AND
na.visibility & 1 > 0 AND
na.updateTime < 1455885224
ORDER BY na.`updateTime` DESC, na.`id` DESC
LIMIT 0, 10;
For this query, you want an index on skadate_profile(profile_id, status, verified). Also, the following index is probably helpful: skadate_newsfeed_action(status, privacy, updateTime, visibility, userId).
This is probably because of the DISTICT keyword. To remove duplicates MySQL needs to sort the result by every selected column.