【问题标题】:How to Determine Optimal MySQL Table Indexes, When Contents of WHERE Clause Vary?当 WHERE 子句的内容不同时,如何确定最佳 MySQL 表索引?
【发布时间】:2011-11-23 04:12:39
【问题描述】:

我有以下 2 个mysql_queries

查询 1(此查询针对 imgClassimgGender 再重复两次):

$imgFamily_query = "SELECT DISTINCT imgFamily FROM primary_images WHERE '$clause' ";

查询 2:

$query_pag_data = "SELECT imgId, imgURL, imgTitle, view, secondary FROM primary_images WHERE '$clause' ORDER BY imgDate DESC";

如您所见,WHERE 由变量控制。该变量的计算方式如下:

$where_clauses = array();

if ($imgFamilyFalse && $imgClassFalse && $imgGenderFalse) {
    $where_clauses[] = "1=1"; // default do-nothing clause
}

if ($imgFamilyTrue) {
   $where_clauses[] = 'imgFamily=' . "'" . mysql_real_escape_string($_GET['imgFamily']) . "'";
}
if ($imgClassTrue) {
   $where_clauses[] = 'imgClass=' . "'" . mysql_real_escape_string($_GET['imgClass']) . "'";
}
if ($imgGenderTrue) {
   $where_clauses[] = 'imgGender=' . "'" . mysql_real_escape_string($_GET['imgGender']) . "'";
}


$clause = implode(' AND ', $where_clauses);

WHERE 子句仅依赖于以下 3 列:

  1. imgFamily
  2. imgClass
  3. imgGender

但是,根据情况,可以使用这些列中的任意 1、2 或 3 列的组合。

我的问题是,在这种情况下我应该如何为primary_images 设置索引?这是一个“只读”表,所以我不担心索引太多。我希望该表在查询中尽可能高效。

我正在考虑使用多列索引,但由于多列索引中的第一列可能不存在,因此索引不起作用。

是否可以设置多个多列索引?还是在这种情况下只在有问题的 3 列中的每一列上放置一个索引会更好?

【问题讨论】:

  • 别忘了在1=1 列上添加索引。
  • @Johan - 我应该在你写它的时候问你这个问题,但是我该如何在1=1 列上放置一个索引呢?一直在想,想不通。
  • 我在开玩笑,这显然是不可能的:-)
  • 而关于性别的索引由于其基数低而无用。所以你应该有 3 个索引: A: 仅在 imgdate 上。 B:关于 imgClass,imgDate C:关于 IngFamily,Imgdate。如果 MySQL 拒绝使用索引,那将是因为跳过索引更快。这通常是因为索引的基数较低。
  • 唯一索引将阻止您在该索引所涵盖的字段中插入具有相同数据的 2 个项目。如果那是你想要的,你应该这样做。唯一索引不会使您的选择更快。它只会减慢您的插入(和更新)速度,因为它必须检查唯一性要求。

标签: mysql database database-design indexing


【解决方案1】:

我猜 imgGender 将只包含 2 或 3 个值 - M、F 和可能的未知数?在这种情况下,它不适合索引。

所以,我认为您可以使用 2 个索引。索引一应该只使用 imgClass,并且当 imgFamily 列不是 where 子句的一部分时会被命中。索引二应该是复合索引,使用imgFamily和imgClass;即使 imgClass 不是 where 子句的一部分,也应该使用 this。

【讨论】:

  • 你是对的; imgGender 仅包含 malefemale,默认为 male。为什么imgGender 是一个糟糕的候选人?你的想法很有趣。有两个复合索引也行吗? imgFamily & imgClassimgClass & imgFamily?
  • +1,@stefmikhail,如果 30% 以上的行具有相同的值,MySQL(实际上是任何 SQL)将拒绝使用索引。这称为低基数。索引是间接查找的一种形式,如果需要查找很大百分比的行,索引会减慢速度。
  • 如果它是一个只读表,第三个索引,仅在imgFamily 上也可能是一个好主意。它是一个较短的索引,并且在仅引用该列时会(稍微)更快地使用。
【解决方案2】:

根据您的情况,最好保留 3 个单独的索引。

【讨论】:

  • 在 where 子句中指定多列时,多列索引可以提高性能。
  • @a'r - 我同意,但是在这种情况下我必须创建 3(我相信)。那样可以么?拥有 3 个不同的多列索引?
  • @stefmikhail,鉴于您的说法,许多索引不是问题,那么您可以添加索引的每个排列,这至少为您提供 15 个索引。
  • @a'r - 15 真的有必要吗?在我看来,3 会 more 绰绰有余:1) imgFamily, imgClass, imgGender 2) imgClass, imgGender, imgFamily 3) imgGender, imgFamily, imgClass
  • 看看你是否在表中使用了 3 个不同的索引,无论出现在哪里的条件都将在索引中扫描。如果 where 子句中不包含某些内容,则不扫描其索引。但是,如果您放置多列索引并且其中一个候选索引不包含在 where 子句中,那么当只需要一个索引时,它就像扫描 2 个索引一样。我在表中使用了 3 个索引。这是安全的。使用3个索引没有问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
  • 2012-12-29
  • 2015-07-18
  • 2020-12-06
相关资源
最近更新 更多