For the query above, the following recommendations will be helpful as part of the SQL tuning process.
You'll find 3 sections below:
The optimization process and recommendations:
- Avoid Calling Functions With Indexed Columns (query line: 20): When a function is used directly on an indexed column, the database's optimizer won’t be able to use the index. For example, if the column `SaleAmount` is indexed, the index won’t be used as it’s wrapped with the function `isnull`. If you can’t find an alternative condition that won’t use a function call, a possible solution is to store the required value in a new indexed column.
- Avoid Calling Functions With Indexed Columns (query line: 21): When a function is used directly on an indexed column, the database's optimizer won’t be able to use the index. For example, if the column `CityId` is indexed, the index won’t be used as it’s wrapped with the function `isnull`. If you can’t find an alternative condition that won’t use a function call, a possible solution is to store the required value in a new indexed column.
- Avoid Calling Functions With Indexed Columns (query line: 22): When a function is used directly on an indexed column, the database's optimizer won’t be able to use the index. For example, if the column `TopLevelCategoryId` is indexed, the index won’t be used as it’s wrapped with the function `isnull`. If you can’t find an alternative condition that won’t use a function call, a possible solution is to store the required value in a new indexed column.
- Avoid Selecting Unnecessary Columns (query line: 2): Avoid selecting all columns with the '*' wildcard, unless you intend to use them all. Selecting redundant columns may result in unnecessary performance degradation.
- Create Optimal Indexes (modified query below): The recommended indexes are an integral part of this optimization effort and should be created before testing the execution duration of the optimized query.
Optimal indexes for this query:
ALTER TABLE `tblBrandDetails` ADD INDEX `tblbranddetails_idx_categoryid_brandid_cityid` (`CategoryId`,`BrandId`,`CityId`);
ALTER TABLE `tblBrands` ADD INDEX `tblbrands_idx_brandid` (`BrandId`);
ALTER TABLE `tblCategory` ADD INDEX `tblcategory_idx_categoryid` (`CategoryId`);
ALTER TABLE `tblCity` ADD INDEX `tblcity_idx_cityid` (`CityId`);
The optimized query:
SELECT
*
FROM
tblBrandDetailUsers tbdu
INNER JOIN
tblBrands tbs
ON tbs.BrandId = tbdu.BrandId
LEFT JOIN
tblBrandDetails tbd
ON tbd.CategoryId = tbdu.CategoryId
AND tbd.BrandId = tbdu.BrandId
AND tbd.CityId = tbdu.CityId
INNER JOIN
tblCategory tc
ON tbdu.CategoryId = tc.CategoryId
INNER JOIN
tblCity tcc
ON tcc.CityId = tbdu.CityId
WHERE
isnull(tbdu.SaleAmount, -1) <> isnull(tbd.SaleAmount, -1)
AND isnull(tbdu.CityId, 0) = 3
AND isnull(tbdu.TopLevelCategoryId, 0) = 2