如何高效地创建索引

How to create indexes efficiently

我想知道如何根据我的数据结构在我的数据库中创建索引。我的大部分查询都是根据 ID 和名称获取数据,以及在分页时加入两个或三个 table。请告知如何根据以下查询制作索引。

查询:1

SELECT DISTINCT topic, type FROM books where type like 'Tutor-Books' order by topic

解释:

id  select_type table   type    possible_keys   key key_len ref rows    Extra   
1   SIMPLE  books   range   faith   faith   102 NULL    132 Using index condition; Using temporary; Using filesort

查询:2

SELECT  books.name, books.name2, books.id, books.image, books.faith,
        books.topic, books.downloaded, books.viewed, books.language,
        books.size, books.author as author_id, authors.name as author_name,
        authors.aid
    from  books
    LEFT JOIN  authors ON books.author = authors.aid
    WHERE  books.id = '".$id."'
      AND  status = 1 

解释:

id  select_type table   type    possible_keys   key key_len ref rows    Extra   
1   SIMPLE  books   const   PRIMARY PRIMARY 4   const   1   NULL
1   SIMPLE  authors const   aid aid 4   const   1   NULL

在相同查询 returns 总计:

的偏移量情况下,我可以使用索引进行分页吗
SELECT  SQL_CALC_FOUND_ROWS books.name, books.name2, books.id,
        books.image, books.topic, books.author as author_id,
        authors.name as author_name, authors.aid
    from  books
    LEFT JOIN  authors ON books.author = authors.aid
    WHERE  books.author = '$pid'
      AND  status = 1
    ORDER BY  books.name
    LIMIT  $limit OFFSET $offset 

创建索引后是否需要更新我的查询。还请建议 table 格式应该是什么。

显示创建 TABLE 本书:

Table   Create Table    
books   CREATE TABLE `books` (
 `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
 `name2` varchar(150) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
 `author` int(100) NOT NULL,
 `translator` int(120) NOT NULL,
 `publisher` int(100) NOT NULL,
 `pages` int(50) NOT NULL,
 `date` varchar(50) CHARACTER SET latin1 NOT NULL,
 `downloaded` int(100) NOT NULL,
 `alt_lnk` text NOT NULL,
 `viewed` int(100) NOT NULL,
 `language` varchar(100) CHARACTER SET latin1 NOT NULL,
 `image` varchar(200) CHARACTER SET latin1 NOT NULL,
 `faith` varchar(100) CHARACTER SET latin1 NOT NULL,
 `id` int(100) NOT NULL AUTO_INCREMENT,
 `sid` varchar(1200) CHARACTER SET latin1 DEFAULT NULL,
 `topic` varchar(100) CHARACTER SET latin1 NOT NULL,
 `last_viewed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 `size` double NOT NULL,
 `status` int(2) NOT NULL DEFAULT '0',
 `is_scroll` int(2) NOT NULL,
 `is_downloaded` int(2) NOT NULL,
 `pdf_not_found` int(2) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `name` (`name`),
 KEY `downloaded` (`downloaded`),
 KEY `name2` (`name2`),
 KEY `topic` (`topic`),
 KEY `faith` (`faith`)
) ENGINE=InnoDB AUTO_INCREMENT=12962 DEFAULT CHARSET=utf8

您的显示宽度有点古怪,但这不会造成问题。

查询 1:

  • 您使用的 LIKE 运算符没有通配符搜索 %。您可以将其与 = 运算符交换。
  • 我在你的 SHOW CREATE TABLE 中没有看到列 type -- 但你似乎没有索引,除非你将它重命名为 faith .
  • 需要输入字符串吗?它可以抽象为 types table 然后加入反对使用整数吗?或者,如果您有固定数量且不太可能更改的类型,您可以使用 enum?

查询 2:

  • 您不需要引用字符串,这也可能容易受到 SQL 注入的攻击。改为 ='.intval($id).'
  • 确保您在 authors.aid 上有一个索引,并且它们属于同一类型。
where type like 'Tutor-Books' order by topic  (or:)
where type   =  'Tutor-Books' order by topic
--> INDEX(type, topic)

where type like '%Tutor-Books' order by topic
--> INDEX(topic) -- the leading % prevents indexing

LEFT JOIN  authors ON books.author = authors.aid
--> PRIMARY KEY(aid)

你真的需要LEFT JOIN吗?如果您可以将其更改为 JOIN,优化器可能可以从 authors 开始。如果是,那么

--> INDEX(author) -- in `books`

My cookbook 用于建立索引。

其他提示:

  • INT(100)INT(2) 相同 -- 每个都是一个 4 字节有符号整数。阅读有关数字 0..255 等的 TINYINT UNSIGNED。将其用于您的标志(状态、is_scroll 等)
  • DATE是一种数据类型;如果您想比较或订购,使用 VARCHAR 是有问题的。
  • 了解复合索引,比如我的第一个例子。