Here is my table:
CREATE TABLE `cerp_oms_order` (
`id` bigint NOT NULL,
`company_id` bigint NOT NULL,
`order_no` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`source_type` int NOT NULL,
`shop_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`outer_shop` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`origin_status` int NOT NULL,
`system_status` int NOT NULL,
`created_time` datetime DEFAULT NULL,
`paid_time` datetime DEFAULT NULL,
`sent_time` datetime DEFAULT NULL,
`end_time` datetime DEFAULT NULL,
`modify_time` datetime DEFAULT NULL,
`delivery_deadline_time` datetime DEFAULT NULL,
`amount` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`spu_kind` int NOT NULL,
`sku_kind` int NOT NULL,
`total_quantity` decimal(16,4) NOT NULL,
`buyer_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`outer_buyer_identifier` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`tax_info` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`warehouse_owner` int DEFAULT NULL,
`warehouse_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`logistics_type` int NOT NULL,
`logistics_outer_info` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`delivery_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`delivery_no` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`wave_no` varchar(64) DEFAULT '',
`is_deleted` tinyint NOT NULL DEFAULT '0',
`backend_processing_type` tinyint NOT NULL,
`create_type` tinyint NOT NULL,
`is_hang_up` tinyint NOT NULL,
`hang_up_case_type` smallint DEFAULT NULL,
`hang_up_case_id` bigint DEFAULT NULL,
`rc_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`rm_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`vat` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`weight` decimal(16,4) NOT NULL DEFAULT '0.0000',
`volume` decimal(16,4) NOT NULL DEFAULT '0.0000',
`is_abnormal` tinyint NOT NULL DEFAULT '0',
`estimate_profit` decimal(16,4) NOT NULL DEFAULT '0.0000',
`business_man_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`business_man` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`currency` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`net_amount_summary` decimal(19,4) NOT NULL,
`domestic_amount` decimal(19,4) NOT NULL,
`secret_key` varchar(64) DEFAULT '',
`secretKey` varchar(255) DEFAULT NULL,
`sale_id` bigint DEFAULT NULL,
`total_refund_include_tax` decimal(16,4) NOT NULL DEFAULT '0.0000',
`total_refund_money` decimal(16,4) NOT NULL DEFAULT '0.0000',
`total_refund_tax` decimal(16,4) NOT NULL DEFAULT '0.0000',
`total_return_goods` decimal(16,2) NOT NULL DEFAULT '0.00',
PRIMARY KEY (`id`),
UNIQUE KEY `key_order_no` (`order_no`),
KEY `idx_order_company_id` (`company_id`,`created_time`),
KEY `IDX_RM_TIME` (`rm_time`),
KEY `IDX_IS_ABNORMAL` (`is_abnormal`),
KEY `cerp_oms_order_company_id_index` (`company_id`),
KEY `idx_order_company_status_deleted` (`company_id`,`is_deleted`,`system_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='system order table'
explain select *
from cerp_oms_order
inner join (select id
from cerp_oms_order
where source_type = 43
order by created_time) as tmp using (id);
id
select_type
table
partitions
type
possible_keys
key
key_len
ref
rows
filtered
Extra
1
SIMPLE
cerp_oms_order
null
ALL
PRIMARY
null
null
null
60787
10
Using where
1
SIMPLE
cerp_oms_order
null
eq_ref
PRIMARY
PRIMARY
8
cerp_oms_1.cerp_oms_order.id
1
100
null
using inner join execution: 7 ms, fetching: 109 ms
VS
explain
select *
from cerp_oms_order
where source_type = 43
order by created_time;
id
select_type
table
partitions
type
possible_keys
key
key_len
ref
rows
filtered
Extra
1
SIMPLE
cerp_oms_order
null
ALL
null
null
null
null
60787
10
Using where; Using filesort
using simple where clause execution: 80 ms, fetching: 138 ms
I don't understand why use inner join can speed up my sql?
If you had
INDEX(source_type, created_time)
both formulations would run faster. And, I think, the second would be faster.
As for "why". Look at what the second does:
Scan the entire table ("table scan") looking for rows with source_type = 43.
For each matching row, gather all the columns (*) from the row, into a temp table.
Sort that temp table. Note that this is bulkier than with the subquery that hauls around only id.
Deliver the results.
With the INDEX I suggest:
Look in the index's B+Tree for all 'rows' with source_type = 43.
Since those rows are sorted by created_time, not "sort" pass will be needed now or later.
Each of those index rows will contain id. (That's the way InnoDB gets to the rest of the columns), so
Look up the desired rows in the data's B+Tree and pull out all (*) the columns.
Deliver them.
Note that the JOIN version works essentially the same, but, technically speaking, the ORDER BY may get lost. If it does get lost, you would need to add a second ORDER BY, thereby forcing a sort.
(Unrelated) Your "KEY cerp_oms_order_company_id_index (company_id)," can be dropped since there are two other indexes starting with company_id.
More on optimizing indexes: Index Cookbook
the below query has some problems so can we able to optimize the query with the current index format cuz the table size is huge so I don't know what to do.
Query:
select
`sale_amount`,
`provider_transaction_id`,
`id` as `acc_id`,
`status`,
`service_id`,
`provider_status`,
`is_sale_settled`,
CASE WHEN status = 1
and is_sale_settled = 1 then 4 WHEN status = 1
and is_sale_settled = 0 then 3 ELSE 5 END AS acc_ics_status,
`system_transaction_id`,
`engine_transaction_id`,
`transaction_date`,
`created_at` as `transaction_date_time`,
HOUR(created_at) as transaction_hour
from
`st_ret_txn_aeps`
where
`created_at` >= '2022-10-03 14:45:01'
and `created_at` <= '2022-10-03 14:48:00'
and `service_id` = 14
and `transaction_date` = '2022-10-03'
Row scans;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: st_ret_txn_aeps
partitions: NULL
type: index_merge
possible_keys: transaction_id_sevrice_id_unique,st_ret_txn_aeps_service_id_index,idx_txn_date
key: idx_txn_date,st_ret_txn_aeps_service_id_index
key_len: 3,1
ref: NULL
rows: 122328
filtered: 11.11
Extra: Using intersect(idx_txn_date,st_ret_txn_aeps_service_id_index); Using where
1 row in set, 1 warning (0.00 sec)
Table structure;
*************************** 1. row ***************************
Table: st_ret_txn_aeps
Create Table: CREATE TABLE `st_ret_txn_aeps` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`service_id` tinyint(4) NOT NULL,
`transaction_type_id` tinyint(4) NOT NULL,
`business_org_id` int(10) unsigned NOT NULL,
`sub_agent_id` int(11) DEFAULT NULL,
`agent_id` int(10) unsigned DEFAULT NULL,
`business_org_user_id` int(10) unsigned NOT NULL,
`business_org_sub_user_id` int(10) unsigned DEFAULT NULL,
`retailer_category_code` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`rate_profile_id` int(11) DEFAULT '0',
`wallet_type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`business_org_pan` varchar(12) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`business_org_gstin` varchar(25) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`operator_id` int(10) unsigned NOT NULL,
`operator_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`product_id` int(11) DEFAULT NULL,
`sub_product_id` int(11) DEFAULT NULL,
`provider_id` int(10) unsigned NOT NULL,
`provider_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`branch_id` int(11) NOT NULL DEFAULT '0',
`branch_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`sale_amount` double NOT NULL,
`total_b_org_charges` double NOT NULL,
`total_b_org_comm_tds` double DEFAULT '0',
`total_b_org_commission` double NOT NULL,
`final_debit_value` double NOT NULL,
`balance_after_txn` double NOT NULL,
`system_transaction_id` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`engine_transaction_id` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`provider_transaction_id` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`operator_transaction_id` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`reference_1` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`reference_2` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`reference_3` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`reference_4` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`reference_5` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`business_org_markup` double NOT NULL DEFAULT '0',
`refund_date` date DEFAULT NULL,
`remark` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`is_invoice_data_generated` tinyint(1) NOT NULL,
`status` tinyint(4) NOT NULL COMMENT '1: success ,2: failed',
`provider_status` tinyint(4) DEFAULT NULL,
`provider_status_old` tinyint(4) DEFAULT NULL,
`transaction_date` date NOT NULL,
`customer_id` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`customer_mobile_no` varchar(15) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`app_type` varchar(40) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '1:WEBPOS 2:ANDROID',
`is_cashout_sale` tinyint(1) NOT NULL,
`is_sale_settled` tinyint(1) NOT NULL,
`settlement_date` date DEFAULT NULL,
`analytics_sync_status` tinyint(1) DEFAULT NULL,
`analytics_sync_status_refund` tinyint(1) DEFAULT NULL,
`invoice_data_id` int(11) DEFAULT NULL,
`credit_note_data_id` int(11) DEFAULT NULL,
`status_updated_at` bigint(20) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `transaction_id_sevrice_id_unique` (`service_id`,`engine_transaction_id`),
UNIQUE KEY `system_transaction_id_unique` (`system_transaction_id`),
KEY `st_ret_txn_aeps_service_id_index` (`service_id`),
KEY `st_ret_txn_aeps_business_org_id_index` (`business_org_id`),
KEY `st_ret_txn_aeps_agent_id_index` (`agent_id`),
KEY `st_ret_txn_aeps_business_org_user_id_index` (`business_org_user_id`),
KEY `st_ret_txn_aeps_system_transaction_id_index` (`system_transaction_id`),
KEY `st_ret_txn_aeps_refund_date_index` (`refund_date`),
KEY `idx_txn_date` (`transaction_date`),
KEY `st_ret_txn_aeps_settlement_date_index` (`settlement_date`),
KEY `status_updated_at_idx` (`status_updated_at`)
) ENGINE=InnoDB AUTO_INCREMENT=122756253 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
yeah I know if we create an index for the created_at column means the problem will solve does this have any other way to optimize?
Well, you could delete all the data, then the query would be very quick (just kidding)!
Honestly, you need to create the index to optimize this query. The best index for this query would be a compound index on (service_id, transaction_date, created_at) in that order.
There are at least three ways to create the index without much downtime:
pt-online-schema-change
gh-ost
Create the index on a replica database, then when the index is ready, switch the app to use the replica
At my last job we used pt-online-schema-change. While I worked there we executed over 75,000 ALTER TABLEs in production during peak hours, without downtime. Some of the tables were larger than yours.
The below query finds one id by using the below query format but it seems I have indexed all columns, but it took time to execute between 54.3 seconds - 1.2 mins. What can I try next?
Query:
select
op.ord_prod_id
FROM
ordered_product op,
payment_type pt,
account a,
service s,
payment_method pm,
acct_order ao,
acct_order_item aoi
WHERE
(
(
op.type = 1
OR op.type = 2
)
AND (
pt.description = 'Levis'
AND op.validity_end_date < '2022-09-18 11:24:08 Etc/GMT'
AND op.validity_end_date >= '2022-09-18 00:00:00 Etc/GMT'
AND op.acct_status_id = 1
AND op.is_Renewable = 'T'
AND a.bu_id = 103
)
)
AND pm.type_id = pt.id
AND s.acct_id = a.acct_id
AND op.serv_id = s.serv_id
AND ao.pay_meth_id = pm.pay_method_id
AND aoi.order_id = ao.order_id
AND aoi.ord_prod_id = op.ord_prod_id
ORDER BY
op.validity_end_date ASC
explain plan
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pt
partitions: NULL
type: ref
possible_keys: PRIMARY,idx_pmttype_descrip,idx_description
key: idx_pmttype_descrip
key_len: 32
ref: const
rows: 1
filtered: 100.00
Extra: Using index; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pm
partitions: NULL
type: ref
possible_keys: PRIMARY,payment_method_type_id,Idx_type_id,idx_type_id_zip_code_last_digits
key: payment_method_type_id
key_len: 10
ref: ccbuser.pt.id
rows: 3297
filtered: 100.00
Extra: Using index
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: ao
partitions: NULL
type: ref
possible_keys: PRIMARY,idx_pay_meth_id
key: idx_pay_meth_id
key_len: 11
ref: ccbuser.pm.pay_method_id
rows: 2
filtered: 100.00
Extra: Using index
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: aoi
partitions: NULL
type: ref
possible_keys: idx_accttorderitem_orderid,idx_ord_prod_id
key: idx_accttorderitem_orderid
key_len: 10
ref: ccbuser.ao.order_id
rows: 1
filtered: 100.00
Extra: NULL
*************************** 5. row ***************************
id: 1
select_type: SIMPLE
table: op
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,idx_ord_prod_servid,idx_ord_prod_statprod,idx_ordprod_type,idx_ord_prod_ve_date,idx_ord_prod_acct_status_id,idx_combo,idx_is_renewable,idx_validity_package_ind_acct_status
key: PRIMARY
key_len: 10
ref: ccbuser.aoi.ord_prod_id
rows: 1
filtered: 5.00
Extra: Using where
*************************** 6. row ***************************
id: 1
select_type: SIMPLE
table: s
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,idx_service_acctid
key: PRIMARY
key_len: 10
ref: ccbuser.op.serv_id
rows: 1
filtered: 100.00
Extra: NULL
*************************** 7. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,idx_account_buidasid,idx_combo,idx_bu_id,idx_1
key: PRIMARY
key_len: 10
ref: ccbuser.s.acct_id
rows: 1
filtered: 5.00
Extra: Using where
7 rows in set, 11 warnings (0.03 sec)
i have given show warnings;
*************************** 1. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 11:24:08 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 2. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 00:00:00 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 3. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 11:24:08 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 4. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 11:24:08 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 5. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 11:24:08 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 6. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 11:24:08 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 7. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 00:00:00 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 8. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 00:00:00 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 9. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 00:00:00 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 10. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2022-09-18 00:00:00 Etc/GMT' for column 'validity_end_date' at row 1
*************************** 11. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select
.`op`.`ord_prod_id` AS `ord_prod_id`
from
`ordered_product` `op`
join `payment_type` `pt`
join `account` `a`
join `service` `s`
join `payment_method` `pm`
join `acct_order` `ao`
join `acct_order_item` `aoi`
where
(
(
`op`.`ord_prod_id` = `aoi`.`ord_prod_id`
)
and (
`aoi`.`order_id` = `ao`.`order_id`
)
and (
`ao`.`pay_meth_id` = `pm`.`pay_method_id`
)
and (
`s`.`serv_id` = `op`.`serv_id`
)
and (
`a`.`acct_id` = `s`.`acct_id`
)
and (
`pm`.`type_id` = `pt`.`id`
)
and (
`op`.`is_Renewable` = 'T'
)
and (
`pt`.`description` = 'Credit Card'
)
and (
(`op`.`type` = 1)
or (`op`.`type` = 2)
)
and (
`op`.`validity_end_date` < '2022-09-18 11:24:08 Etc/GMT'
)
and (
`op`.`validity_end_date` >= '2022-09-18 00:00:00 Etc/GMT'
)
and (
`op`.`acct_status_id` = 1
)
and (`a`.`bu_id` = 103)
)
order by
`op`.`validity_end_date`
All the rows scan one row, some of them scan 3k for one row - do I have to use str_to_date functions for the above one, are there any ways to improve performance?
Table structure:
Table: ordered_product
Create Table: CREATE TABLE `ordered_product` (
`acct_status_id` decimal(22,0) NOT NULL,
`anual_prepay_ind` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`bill_end_date` datetime DEFAULT NULL,
`bill_start_date` datetime DEFAULT NULL,
`equip_id` decimal(22,0) DEFAULT NULL,
`ord_prod_id` decimal(22,0) NOT NULL,
`package_id` decimal(22,0) DEFAULT NULL,
`package_ind` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`parent_ord_prod_id` decimal(22,0) DEFAULT NULL,
`prod_id` decimal(22,0) DEFAULT NULL,
`quantity` decimal(38,0) DEFAULT NULL,
`remove_flag` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`serv_id` decimal(22,0) NOT NULL,
`srv_end_date` datetime DEFAULT NULL,
`srv_start_date` datetime DEFAULT NULL,
`split_prod_id` decimal(22,0) DEFAULT NULL,
`term` decimal(22,0) DEFAULT NULL,
`type` decimal(22,0) DEFAULT NULL,
`tax_charged` decimal(20,6) DEFAULT NULL,
`comments` varchar(4000) DEFAULT NULL,
`reason_code_id` decimal(20,0) DEFAULT NULL,
`price_charged` decimal(20,2) DEFAULT NULL,
`validity_period` varchar(20) DEFAULT NULL,
`validity_duration` decimal(38,0) DEFAULT NULL,
`validity_end_date` datetime DEFAULT NULL,
`coupon_amount` decimal(20,2) DEFAULT NULL,
`coupon_code` varchar(100) DEFAULT NULL,
`applied_wallet_amount` decimal(20,2) DEFAULT NULL,
`applied_rate_type` varchar(100) DEFAULT NULL,
`partner_domain` varchar(100) DEFAULT NULL,
`is_Renewable` varchar(1) DEFAULT NULL,
`coupon_external_id` varchar(256) DEFAULT NULL,
`validity_extended_date` datetime DEFAULT NULL,
`cancellation_date` datetime DEFAULT NULL,
`rec_indicator` varchar(1) DEFAULT NULL,
`suspend_start_date` datetime DEFAULT NULL,
`suspend_end_date` datetime DEFAULT NULL,
`suspend_duration` decimal(20,0) DEFAULT NULL,
`commitment_end_date` datetime DEFAULT NULL,
`modified_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`contact_id` varchar(30) DEFAULT NULL,
`subscription_status_id` decimal(22,0) DEFAULT NULL,
`bu_charged_currency_id` decimal(38,0) DEFAULT NULL,
`currency_code` varchar(200) DEFAULT NULL,
`legacy_id` varchar(200) DEFAULT NULL,
`app_service_id` varchar(200) DEFAULT NULL,
`app_channel_name` varchar(200) DEFAULT NULL,
`applied_prod_rate_id` decimal(22,0) DEFAULT NULL,
`applied_prod_rate_in_charged_currency_id` decimal(22,0) DEFAULT NULL,
`applied_prod_price` decimal(22,0) DEFAULT NULL,
`bill_to_parent` varchar(1) DEFAULT NULL,
PRIMARY KEY (`ord_prod_id`),
KEY `idx_ord_prod_servid` (`serv_id`),
KEY `idx_ord_prod_statprod` (`acct_status_id`,`prod_id`,`package_id`),
KEY `idx_ord_prod_bs_date` (`bill_start_date`),
KEY `idx_ord_prod_be_date` (`bill_end_date`),
KEY `ordered_product_modified_ts` (`modified_ts`),
KEY `idx_ordprod_type` (`type`),
KEY `idx_ord_prod_ve_date` (`validity_end_date`),
KEY `idx_ord_prod_prod_id` (`prod_id`),
KEY `idx_ord_prod_srv_start_date` (`srv_start_date`),
KEY `idx_ord_prod_pack_id` (`package_id`),
KEY `idx_ord_prod_acct_status_id` (`acct_status_id`),
KEY `idx_ord_prod_validity_extend_dt` (`validity_extended_date`),
KEY `idx_remove_flag` (`remove_flag`),
KEY `idx_ord_prod_srv_end_date` (`srv_end_date`),
KEY `idx_subscription_status_id` (`subscription_status_id`),
KEY `idx_coupon_code` (`coupon_code`),
KEY `idx_parent_ord_prod_id` (`parent_ord_prod_id`),
KEY `idx_combo` (`type`,`serv_id`),
KEY `idx_is_renewable` (`is_Renewable`),
KEY `idx_package_ind` (`package_ind`),
KEY `idx_validity_package_ind_acct_status` (`validity_end_date`,`package_ind`,`acct_status_id`),
KEY `idx_legacyid` (`legacy_id`),
KEY `idx_cancellation_date` (`cancellation_date`),
KEY `idx_suspend_start_date` (`suspend_start_date`),
KEY `idx_suspend_end_date_validity_end_date_combo` (`suspend_end_date`,`validity_end_date`,`acct_status_id`,`is_Renewable`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Table: payment_type
Create Table: CREATE TABLE `payment_type` (
`auto_pay_capable_ind` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`can_post_credit_ind` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`check_number_ind` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`description` varchar(30) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`display_order` decimal(22,0) NOT NULL,
`id` decimal(22,0) NOT NULL,
`requires_gateway_ind` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`display_name` varchar(30) DEFAULT NULL,
`modified_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`image_url` varchar(4096) DEFAULT NULL,
`short_code` varchar(20) DEFAULT NULL,
`payment_group` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_pmttype_descrip` (`description`),
KEY `idx_display_name` (`display_name`),
KEY `idx_description` (`description`),
KEY `idx_payment_group` (`payment_group`),
KEY `idx_modified_ts` (`modified_ts`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Table: account
Create Table: CREATE TABLE `account` (
`acct_id` decimal(22,0) NOT NULL,
`acct_status_id` decimal(22,0) NOT NULL,
`acct_type_id` decimal(22,0) DEFAULT NULL,
`attach_bill_cycle` char(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`bb_acct_id` varchar(256) DEFAULT NULL,
`bill_del_type_id` decimal(22,0) DEFAULT NULL,
`acct_bill_mode` varchar(20) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`bu_id` decimal(22,0) NOT NULL,
`acct_comment` varchar(500) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`compliment_acct` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`contact_id` decimal(22,0) NOT NULL,
`corporate_id` decimal(22,0) DEFAULT NULL,
`create_date` datetime NOT NULL,
`customer_id` varchar(100) DEFAULT NULL,
`direct_acct` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`do_not_auto_script` char(5) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`email_inv_format` varchar(25) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`external_id_prefix` varchar(6) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`external_id_suffix` varchar(25) DEFAULT NULL,
`inter_pic_id` varchar(4) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`intra_pic_id` varchar(4) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`legacy_id` decimal(22,0) DEFAULT NULL,
`parent_id` decimal(22,0) DEFAULT NULL,
`partner_id` decimal(22,0) DEFAULT NULL,
`psa_acct_id` varchar(20) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`acct_reg_num` varchar(25) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`sales_method` varchar(100) DEFAULT NULL,
`shipping_add_id` decimal(22,0) DEFAULT NULL,
`tax_exempt` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`tax_number` varchar(20) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`tv_dma_id` varchar(30) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`status_change_date` datetime DEFAULT NULL,
`external_creation_date` date DEFAULT NULL,
`sales_person` varchar(200) DEFAULT NULL,
`offer_type` varchar(50) DEFAULT NULL,
`cancel_reasons_id` int(38) DEFAULT NULL,
`acct_addl_info_id` decimal(38,0) DEFAULT NULL,
`vpn_id` decimal(22,0) DEFAULT NULL,
`verified` varchar(1) DEFAULT NULL,
`verified_channel` varchar(50) DEFAULT NULL,
`active_logins_count` decimal(20,0) DEFAULT NULL,
`acct_role_id` decimal(20,0) DEFAULT NULL,
`mso_id` varchar(200) DEFAULT NULL,
`mso_name` varchar(200) DEFAULT NULL,
`anonymized` varchar(1) DEFAULT NULL,
`parental_control` varchar(1) DEFAULT NULL,
`act_state_id` decimal(38,0) DEFAULT NULL,
`verified_date` datetime DEFAULT NULL,
`complaintmode_acct` varchar(1) DEFAULT NULL,
`modified_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`mobile_verified` varchar(1) DEFAULT NULL,
`acct_sub_type_id` decimal(22,0) DEFAULT NULL,
`created_by` decimal(22,0) DEFAULT NULL,
`ip_address` varchar(50) DEFAULT NULL,
PRIMARY KEY (`acct_id`),
KEY `idx_account_customer_id` (`customer_id`),
KEY `idx_account_buidasid` (`bu_id`,`acct_status_id`),
KEY `idx_account_bbaccountid` (`bb_acct_id`),
KEY `idx_create_date` (`create_date`),
KEY `idx_contact_id` (`contact_id`),
KEY `idx_attach_bill_cycle` (`attach_bill_cycle`),
KEY `idx_act_state` (`act_state_id`),
KEY `idx_accountt_legacyid` (`legacy_id`),
KEY `account_modified_ts` (`modified_ts`),
KEY `idx_account_acctroleid` (`acct_role_id`),
KEY `idx_extrnl_suffix` (`external_id_suffix`),
KEY `idx_extrnl_prefix` (`external_id_prefix`),
KEY `idx_combo` (`bu_id`,`psa_acct_id`),
KEY `idx_bu_id` (`bu_id`),
KEY `idx_acct_reg_num` (`acct_reg_num`),
KEY `idx_acct_stat_id` (`acct_status_id`),
KEY `account_idx_combo4` (`tax_number`,`acct_id`,`contact_id`,`bu_id`),
KEY `idx_1` (`bu_id`,`customer_id`),
KEY `idx_acct_type_id` (`acct_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Table: service
Create Table: CREATE TABLE `service` (
`acct_id` decimal(22,0) NOT NULL,
`acct_status_id` decimal(22,0) DEFAULT NULL,
`do_not_auto_script` char(5) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`end_date` datetime DEFAULT NULL,
`last_billed` datetime DEFAULT NULL,
`loc_id` decimal(22,0) DEFAULT NULL,
`serv_id` decimal(22,0) NOT NULL,
`start_date` datetime NOT NULL,
`type` decimal(22,0) DEFAULT NULL,
`suspend_start_date` date DEFAULT NULL,
`suspend_end_date` date DEFAULT NULL,
`pending_suspension_date` date DEFAULT NULL,
`reactivation_date` date DEFAULT NULL,
`suspend_duration` decimal(20,0) DEFAULT NULL,
`modified_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`serv_id`),
KEY `idx_service_acctid` (`acct_id`),
KEY `idx_service_locid` (`loc_id`),
KEY `service_modified_ts` (`modified_ts`),
KEY `idx_service_modified_ts` (`modified_ts`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Table: payment_method
Create Table: CREATE TABLE `payment_method` (
`account_number` varchar(200) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`bob_id` decimal(22,0) DEFAULT NULL,
`closed_date` datetime DEFAULT NULL,
`pay_method_id` decimal(22,0) NOT NULL,
`start_date` datetime NOT NULL,
`type_id` decimal(22,0) NOT NULL,
`credit_card_type_id` decimal(22,0) DEFAULT NULL,
`expiration_date` datetime DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
`pay_meth_type_id` decimal(22,0) NOT NULL,
`security_code` varchar(100) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`str_addr` varchar(250) DEFAULT NULL,
`zip_code` varchar(10) DEFAULT NULL,
`acct_type_id` decimal(22,0) DEFAULT NULL,
`bank_name` varchar(512) DEFAULT NULL,
`bank_phone` varchar(15) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`rtn` varchar(20) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`city` varchar(100) DEFAULT NULL,
`drivers_license` varchar(20) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`email` varchar(256) DEFAULT NULL,
`sent_out` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`ssn` varchar(30) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`state` varchar(4) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`country` varchar(30) DEFAULT NULL,
`storage_token` varchar(200) DEFAULT NULL,
`payer_id` varchar(50) DEFAULT NULL,
`last_digits` varchar(4) DEFAULT NULL,
`ref_number` varchar(50) DEFAULT NULL,
`phone_number` varchar(20) DEFAULT NULL,
`dc_code` varchar(20) DEFAULT NULL,
`xid` varchar(250) DEFAULT NULL,
`eci` varchar(5) DEFAULT NULL,
`cavv` varchar(250) DEFAULT NULL,
`ucaf_authentication_data` varchar(250) DEFAULT NULL,
`ucaf_collection_ind` varchar(5) DEFAULT NULL,
`subscription_id` varchar(50) DEFAULT NULL,
`effort_id` decimal(10,0) DEFAULT NULL,
`receipt_data` longtext,
`transaction_id` varchar(512) DEFAULT NULL,
`org_transaction_id` varchar(512) DEFAULT NULL,
`tax_area_id` varchar(30) DEFAULT NULL,
`modified_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`nick_name` varchar(100) DEFAULT NULL,
`iin` varchar(8) DEFAULT NULL,
`allow_unlimited` tinyint(1) DEFAULT NULL,
`name_of_bank` varchar(100) DEFAULT NULL,
`card_number` varchar(100) DEFAULT NULL,
`pin` varchar(20) DEFAULT NULL,
`card_finger_print` varchar(200) DEFAULT NULL,
`card_issuer_country` varchar(30) DEFAULT NULL,
`card_service_provider` varchar(512) DEFAULT NULL,
PRIMARY KEY (`pay_method_id`),
KEY `payment_method_modified_ts` (`modified_ts`),
KEY `idx_pmtmethod_transid` (`transaction_id`),
KEY `idx_payment_method_start_dt` (`start_date`),
KEY `payment_method_start_date` (`start_date`),
KEY `payment_method_bob_id` (`bob_id`),
KEY `payment_method_type_id` (`type_id`),
KEY `idx_pm_accountno` (`account_number`),
KEY `idx_exp_date` (`expiration_date`),
KEY `idx_org_transaction_id` (`org_transaction_id`),
KEY `idx_transaction_id` (`transaction_id`),
KEY `Idx_bob_id` (`bob_id`),
KEY `idx_account_number` (`account_number`),
KEY `Idx_type_id` (`type_id`),
KEY `i_modified_ts` (`modified_ts`),
KEY `idx_last_digits` (`last_digits`),
KEY `idx_ref_number` (`ref_number`),
KEY `ix_refer_num` (`ref_number`),
KEY `idx_zipcode` (`zip_code`),
KEY `idx_card_fingerprint` (`card_finger_print`),
KEY `idx_phone_number` (`phone_number`),
KEY `idx_type_id_zip_code_last_digits` (`type_id`,`zip_code`,`last_digits`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Table: acct_order
Create Table: CREATE TABLE `acct_order` (
`acct_id` decimal(22,0) NOT NULL,
`ao_wf_instance_id` decimal(22,0) DEFAULT NULL,
`comm` varchar(4000) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`comment_id` decimal(38,0) DEFAULT NULL,
`external_status` varchar(50) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`house_hold_user` varchar(60) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`legacy_id` varchar(200) DEFAULT NULL,
`modify_date` datetime NOT NULL,
`order_id` decimal(22,0) NOT NULL,
`promise_date` datetime NOT NULL,
`remove_flag` varchar(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`serv_id` decimal(22,0) DEFAULT NULL,
`txn_id` decimal(22,0) DEFAULT NULL,
`workflow_instance_id` decimal(22,0) DEFAULT NULL,
`external_order_id` varchar(200) DEFAULT NULL,
`ref_number` varchar(200) DEFAULT NULL,
`pmt_profile_id` varchar(2048) DEFAULT NULL,
`pay_meth_id` decimal(22,0) DEFAULT NULL,
`modified_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`txn_summary_id` int(38) DEFAULT NULL,
`country` varchar(10) DEFAULT NULL,
`recon_required` varchar(50) DEFAULT NULL,
PRIMARY KEY (`order_id`),
KEY `idx_acctorder_acctid` (`acct_id`),
KEY `idx_acctorder_wfiid` (`workflow_instance_id`),
KEY `idx_acctorder_servid` (`serv_id`),
KEY `idx_ao_mod_dt` (`modify_date`),
KEY `idx_ext_id` (`external_order_id`),
KEY `acct_order_modified_ts` (`modified_ts`),
KEY `idx_pmt_profile_id` (`pmt_profile_id`),
KEY `idx_ref_number` (`ref_number`),
KEY `idx_pay_meth_id` (`pay_meth_id`),
KEY `idx_txn_id` (`txn_id`),
KEY `idx_promise_date` (`promise_date`),
KEY `idx_modified_ts` (`modified_ts`),
KEY `idx_ao_wf_instance_id` (`ao_wf_instance_id`),
KEY `idx_acct_id_legacy_id` (`acct_id`,`legacy_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Table: acct_order_item
Create Table: CREATE TABLE `acct_order_item` (
`modify_date` datetime NOT NULL,
`ord_prod_id` decimal(22,0) NOT NULL,
`order_id` decimal(22,0) NOT NULL,
`order_item_id` decimal(22,0) NOT NULL,
`modified_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`order_item_id`),
KEY `idx_accttorderitem_orderid` (`order_id`),
KEY `idx_ord_prod_id` (`ord_prod_id`),
KEY `acct_order_item_modified_ts` (`modified_ts`),
KEY `idx_acct_order_item_modified_ts` (`modified_ts`),
KEY `idx_modified_ts` (`modified_ts`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Re-arranging your query, you get this...
SELECT
op.ord_prod_id
FROM
account AS a
INNER JOIN
service AS s
ON s.acct_id = a.acct_id
INNER JOIN
ordered_product AS op
ON op.serv_id = s.serv_id
INNER JOIN
acct_order_item AS aoi
ON aoi.ord_prod_id = op.ord_prod_id
INNER JOIN
acct_order AS ao
ON aoi.order_id = ao.order_id
INNER JOIN
payment_method AS pm
ON ao.pay_meth_id = pm.pay_method_id
INNER JOIN
payment_type AS pt
ON pm.type_id = pt.id
WHERE
a.bu_id = 103
AND op.type IN (1,2)
AND op.validity_end_date < '2022-09-18 11:24:08 Etc/GMT'
AND op.validity_end_date >= '2022-09-18 00:00:00 Etc/GMT'
AND op.acct_status_id = 1
AND op.is_Renewable = 'T'
AND pt.description = 'Levis'
ORDER BY
op.validity_end_date ASC
This looks wrong to me, but I can't tell without the database schema.
Here's why I think it's wrong...
Get all accounts with bu_id = 103
Get all of those accounts' services (the same service may appear multiple times)
Get all ordered products associated to those services regardless of account
I strongly suspect that acct_order has an acct_id column, which would likely enable something like this...
SELECT
op.ord_prod_id
FROM
account AS a
INNER JOIN
acct_order AS ao
ON ao.acct_id = a.acct_id
INNER JOIN
payment_method AS pm
ON pm.pay_method_id = ao.pay_meth_id
INNER JOIN
payment_type AS pt
ON pt.id = pm.type_id
INNER JOIN
acct_order_item AS aoi
ON aoi.order_id = ao.order_id
INNER JOIN
ordered_product AS op
ON op.ord_prod_id = aoi.ord_prod_id
--
-- No need to join on service now
--
WHERE
a.bu_id = 103
AND pt.description = 'Levis'
AND op.type IN (1,2)
AND op.acct_status_id = 1
AND op.is_Renewable = 'T'
AND op.validity_end_date >= '2022-09-18 00:00:00 Etc/GMT'
AND op.validity_end_date < '2022-09-18 11:24:08 Etc/GMT'
ORDER BY
op.validity_end_date ASC
That alone will likely reduce the number of rows being processed, and give insights into what indexes you want, potentially being...
account (bu_id, acct_id)
acct_order (acct_id, pay_meth_id, order_id)
payment_method (pay_method_id, type_id) or (type_id, pay_method_id)
payment_type (id, description) or (description, id)
acct_order_item (order_id, ord_prod_id)
ordered_product (type, acct_status_id, is_renewable, validity_end_date, ord_prod_id)
You should also fix the date literal being used in the WHERE clause.
Either way, if you want a more categorical response, you need to include the full schema for those tables, including indexes and foreign keys (to validate your joins) as well as row counts, cardinality, etc (to direct you on index creation, performance tuning, etc).
Edited to remove description per Rick James's comment.
An index designed match your query will make it faster. (But it won't make it correct if it's wrong, just sayin'.)
You filter your ordered_product table on:
type (two values)
account_status_id (equality)
is_Renewable (equality)
validity_end_date (date range)
So try an index with all the equality match columns followed by the range column. MySql can random-access it to the first eligible column and then scan it sequentially. Fast.
CREATE INDEX desc_stat_renew_date ON ordered_product
(acct_status_id, is_Renewable, validity_end_date);
To learn about this, see Marcus Winad's excellent https://use-the-index-luke.com/ .
Pro tip Using mixed case in column or table names can cause confusion if/when you migrate to another server machine. Avoid!
There are several orders in which the Optimizer might evaluate the query. Here are some additional indexes that the optimizer might use, especially if it chooses to start with op.
op: INDEX(acct_status_id, is_Renewable, type, validity_end_date, serv_id, ord_prod_id)
op: INDEX(acct_status_id, is_Renewable, validity_end_date, type, serv_id, ord_prod_id)
I'm getting some strange timing values from Mysql running a "simple" query.
This is the DDL of the table:
CREATE TABLE `frame` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`createdBy` varchar(255) DEFAULT NULL,
`createdDate` datetime(6) NOT NULL,
`lastModifiedBy` varchar(255) DEFAULT NULL,
`lastModifiedDate` datetime(6) DEFAULT NULL,
`sid` varchar(36) NOT NULL,
`version` bigint(20) NOT NULL,
`brand` varchar(255) DEFAULT NULL,
`category` varchar(255) DEFAULT NULL,
`colorCode` varchar(255) DEFAULT NULL,
`colorDescription` varchar(255) DEFAULT NULL,
`description` longtext,
`imageUrl` varchar(255) DEFAULT NULL,
`lastPurchase` datetime(6) DEFAULT NULL,
`lastPurchasePrice` decimal(19,2) DEFAULT NULL,
`lastSell` datetime(6) DEFAULT NULL,
`lastSellPrice` decimal(19,2) DEFAULT NULL,
`line` varchar(255) DEFAULT NULL,
`manufacturer` varchar(255) DEFAULT NULL,
`manufacturerCode` varchar(255) DEFAULT NULL,
`name` varchar(255) NOT NULL,
`preset` bit(1) NOT NULL DEFAULT b'0',
`purchasePrice` decimal(19,2) DEFAULT NULL,
`salesPrice` decimal(19,2) DEFAULT NULL,
`sku` varchar(255) NOT NULL,
`stock` bit(1) NOT NULL DEFAULT b'1',
`thumbUrl` varchar(255) DEFAULT NULL,
`upc` varchar(255) DEFAULT NULL,
`arm` int(11) DEFAULT NULL,
`bridge` int(11) DEFAULT NULL,
`caliber` int(11) DEFAULT NULL,
`gender` varchar(255) DEFAULT NULL,
`lensColor` varchar(255) DEFAULT NULL,
`material` varchar(255) DEFAULT NULL,
`model` varchar(255) NOT NULL,
`sphere` decimal(10,2) DEFAULT NULL,
`type` varchar(255) NOT NULL,
`taxRate_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_k7s4esovkoacsc264bcjrre13` (`sid`),
UNIQUE KEY `UK_ajh6mr6a6qg6mgy8t9nevdym1` (`sku`),
UNIQUE KEY `UK_boqikmg9o89j8q0o5ujkj33b3` (`upc`),
KEY `idx_manufacturer` (`manufacturer`),
KEY `idx_brand` (`brand`),
KEY `idx_line` (`line`),
KEY `idx_colorcode` (`colorCode`),
KEY `idx_preset` (`preset`),
KEY `idx_manufacturer_model_color_caliber` (`manufacturer`,`model`,`colorCode`,`caliber`),
KEY `FK1nau29fd70s1nq905dgs6ft85` (`taxRate_id`),
CONSTRAINT `FK1nau29fd70s1nq905dgs6ft85` FOREIGN KEY (`taxRate_id`) REFERENCES `taxrate` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=392179 DEFAULT CHARSET=utf8;
The query is created programatically from my application. The "strange" syntax (NULL IS NULL OR condition) is very convenient to me in order to make more compact my code and removing the need to create a different query based on the numbers of parameters.
For who understand how Hibernate HQL and JPA works, this is the query:
This query is generated when the user is not setting any filter, so all parameters in my condition are null and this is how the query comes out.
SELECT SQL_NO_CACHE COUNT(frame0_.`id`) AS col_0_0_ FROM `Frame` frame0_
WHERE (NULL IS NULL OR NULL LIKE CONCAT('%', NULL, '%') OR frame0_.`manufacturer` LIKE CONCAT('%', NULL, '%') OR frame0_.`manufacturerCode`=NULL OR frame0_.`sku`=NULL OR frame0_.`upc`=NULL OR frame0_.`line` LIKE CONCAT('%', NULL, '%') OR frame0_.`model` LIKE CONCAT('%', NULL, '%')) AND (NULL IS NULL OR frame0_.`manufacturer`=NULL) AND (NULL IS NULL OR frame0_.`line`=NULL) AND (NULL IS NULL OR frame0_.`caliber`=NULL) AND (NULL IS NULL OR frame0_.`type`=NULL) AND (NULL IS NULL OR frame0_.`material`=NULL) AND (NULL IS NULL OR frame0_.`model`=NULL) AND (NULL IS NULL OR frame0_.`colorCode`=NULL)
The query takes about 0.105s on a table of 137548 rows.
The EXPLAIN of the previous query returns:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE frame0_ \N ALL \ N \N \N \N 137548 100.00 \N
The previous query is identical to this one:
SELECT SQL_NO_CACHE COUNT(frame0_.`id`) AS col_0_0_ FROM `Frame` frame0_
This query takes just 0.05s for the same result in the same table.
Why for Mysql they are different and the first is taking so much time? Is there a way to improve performance of the first query keeping the syntax "NULL IS NULL or condition"?
I think Ryan has right, so the many or statement made the query so bad.
You should programatically build queries for better performance. So if the user not select by a possible filter, than you shouldn't include to the query!
(HQL)
if(!StringUtils.isEmpty(manufacturer)) {
query.and(m.manufacturer.eq(manufacturer))
}
query is simple, as below:
select count(1) from ec_account a join ec_card b on a.id = b.AccountId
there are 2.5 million rows in either ec_account and ec_card.(InnoDB)
here is the execution plan:
execution plan
as you see,
it already added index and used it, but the query still costed almost 60 seconds, is there any way could optimize it except changing database(mariadb has no such choke point as far as i know).
here is table DDL,ec_ccount:
CREATE TABLE `ec_account` (
`Id` varchar(64) NOT NULL,
`AccountType` varchar(32) NOT NULL,
`Name` varchar(32) NOT NULL,
`Status` tinyint(3) unsigned NOT NULL,
`IDCardType` varchar(32) DEFAULT NULL,
`IDCardNo` varchar(64) DEFAULT NULL,
`Password` varchar(256) DEFAULT NULL,
`PasswordHalt` varchar(128) DEFAULT NULL,
`Sex` varchar(8) DEFAULT NULL,
`BirthDay` datetime NOT NULL,
`Mobile` varchar(16) DEFAULT NULL,
`Address` varchar(64) DEFAULT NULL,
`Linkman` varchar(32) DEFAULT NULL,
`LinkmanRelation` varchar(16) DEFAULT NULL,
`LinkmanTel` varchar(16) DEFAULT NULL,
`Remark` varchar(128) DEFAULT NULL,
`Nationality` varchar(32) DEFAULT NULL,
`Nation` varchar(32) DEFAULT NULL,
`MaritalStatus` varchar(8) DEFAULT NULL,
`NativePlace` varchar(64) DEFAULT NULL,
`Occupation` varchar(32) DEFAULT NULL,
`BloodType` varchar(8) DEFAULT NULL,
`Education` varchar(8) DEFAULT NULL,
`LinkmanAddress` varchar(64) DEFAULT NULL,
`HomeAddress` varchar(128) DEFAULT NULL,
`Email` varchar(64) DEFAULT NULL,
`CompanyName` varchar(64) DEFAULT NULL,
`CompanyAddress` varchar(128) DEFAULT NULL,
`CompanyTel` varchar(16) DEFAULT NULL,
`Creator` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`CreateTime` datetime NOT NULL,
`LastModifier` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`LastModifyTime` datetime DEFAULT NULL,
`Avatar` longblob,
PRIMARY KEY (`Id`),
KEY `IX_Name` (`Name`) USING HASH,
KEY `Idx_IDCard_Account` (`IDCardType`,`IDCardNo`) USING HASH,
KEY `Idx_Mobile` (`Mobile`) USING HASH,
KEY `Idx_CreateTime` (`CreateTime`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and ec_card :
CREATE TABLE `ec_card` (
`Id` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`AccountId` varchar(64) NOT NULL,
`CardType` varchar(32) NOT NULL,
`CardNo` varchar(32) NOT NULL,
`Status` tinyint(3) unsigned NOT NULL,
`IsPasswordAuth` tinyint(1) NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `Idx_Unique_AccountId_CardType` (`AccountId`,`CardType`) USING HASH,
UNIQUE KEY `Idx_Unique_CardType_CardNo` (`CardType`,`CardNo`) USING HASH,
KEY `Idx_Uniques_AccountId` (`AccountId`) USING BTREE,
CONSTRAINT `FK_ec_card_ec_account_AccountId` FOREIGN KEY (`AccountId`) REFERENCES `ec_account` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Not without fundamentally changing the query.
There are no conditions on your query! It selects all 2.5 million rows from ec_card, as well as every matching row from ec_account. Reading all this data from disk and sending it over the network is the bottleneck; there is no way to change that without changing what the query does.
Here is a workaround for you. I think it would run much faster, and get the same result.
Calculate the total count of ec_account:
SELECT count(1) AS total_count FROM ec_account;
Calculate the amount of records those existed in ec_account but not existed in ec_card:
SELECT count(1) AS missing_count
FROM ec_account a LEFT JOIN ec_card b on a.id = b.AccountId
WHERE b.AccountId IS NULL;
Matched count = total_count - missing_count
The core problem here is that you combined two large table together, it requires a lot of memory and it apparently needs a lot of time to finish.
try it using correlated subquery. This might help:
select count(1) from ec_account a where exists (select * from ec_card b
where b.AccountId=a.id)
Also, other than indexing following strategies generally help:
- Denormalization
- Caching results
- Using a NoSQL database