如何使用索引优化 MySql table 的搜索速度?
How can I optimize this MySql table for search speed using indexes?
作为一个 MySql 业余爱好者,我想请教一些关于 table 优化和索引使用的建议。
考虑一个 table 包含用户发布的广告。 table 具有以下结构(这是一个 Laravel 实现,但我认为代码不言自明):
Schema::create('advertisements', function (Blueprint $table) {
$table->increments('id'); //PRIMARY KEY AUTOINCREMENTS
$table->text('images'); //TEXT
$table->string('name', 150); //VARCHAR(150)
$table->string('slug'); //VARCHAR(255)
$table->text('description');
$table->string('offer_type',7)->nullable()->index();
$table->float('price')->nullable();
$table->string('deal_type')->nullable()->index();
$table->char('price_period',1)->nullable()->index();
$table->float('price_per_day')->nullable();
$table->float('deposit')->nullable();
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories');
$table->integer('author_id')->unsigned()->nullable();
$table->foreign('author_id')->references('id')->on('users');
$table->timestamps();
});
网站上的用户可以使用多个条件搜索上述 table 中的广告,例如:price
范围、offer_type
、price_period
或 deal_type
.
如您所见,我已经为 offer_type
、price_period
和 deal_type
列编制了索引。据我了解,这会导致数据库为这些列中的值创建一个 BTREE 索引。
但是这些值总是来自预定义的集合:
例如 - price_period
始终是以下之一:NULL, h, d, w, m, y
(小时、天、周、月、年。)
deal_type
列总是 offer
或 demand
.
问题: 如果我有一组列只包含来自预定义的小范围值的值,它是否更好(性能-wise) 为它们创建一个单独的 table 并使用外键而不是索引列? 编辑:经过进一步研究我现在意识到,外键只是一个参考工具而不是性能一个,它们也可以(并且应该)被编入索引。但是,索引外键(一个数字)是否比索引短字符串性能更好?
索引标志和其他低基数列通常没有用。例如,如果 table 的一半具有某个标志的特定值,则忽略该标志上的索引并简单地扫描整个 table 会 更快 。
我们确实需要查看查询以判断需要哪些索引。根据您的提示,我还是会刺...
"such as: price range, offer_type, price_period or deal_type" -- 我假设用户会给出最低和最高价格?然后让我们建立一个 "composite" 索引 ending 和 price_per_day
。他们会始终指定所有其他三列吗?每列都有一个值?如果以上都是,那么这个综合指标是最优的:
INDEX(over_types, price_period, deal_type, price_per_day)
(前3列可以任意排列,但应用到范围的东西必须排在最后。)
如果用户可能只包含其中的一些标志,and/or 可能会包含它们的多个值,那么它会变得更加混乱。观察用户的需求并根据常见查询定制额外的索引。使用此 index cookbook 来帮助构建它们。
作为一个 MySql 业余爱好者,我想请教一些关于 table 优化和索引使用的建议。
考虑一个 table 包含用户发布的广告。 table 具有以下结构(这是一个 Laravel 实现,但我认为代码不言自明):
Schema::create('advertisements', function (Blueprint $table) {
$table->increments('id'); //PRIMARY KEY AUTOINCREMENTS
$table->text('images'); //TEXT
$table->string('name', 150); //VARCHAR(150)
$table->string('slug'); //VARCHAR(255)
$table->text('description');
$table->string('offer_type',7)->nullable()->index();
$table->float('price')->nullable();
$table->string('deal_type')->nullable()->index();
$table->char('price_period',1)->nullable()->index();
$table->float('price_per_day')->nullable();
$table->float('deposit')->nullable();
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories');
$table->integer('author_id')->unsigned()->nullable();
$table->foreign('author_id')->references('id')->on('users');
$table->timestamps();
});
网站上的用户可以使用多个条件搜索上述 table 中的广告,例如:price
范围、offer_type
、price_period
或 deal_type
.
如您所见,我已经为 offer_type
、price_period
和 deal_type
列编制了索引。据我了解,这会导致数据库为这些列中的值创建一个 BTREE 索引。
但是这些值总是来自预定义的集合:
例如 - price_period
始终是以下之一:NULL, h, d, w, m, y
(小时、天、周、月、年。)
deal_type
列总是 offer
或 demand
.
问题: 如果我有一组列只包含来自预定义的小范围值的值,它是否更好(性能-wise) 为它们创建一个单独的 table 并使用外键而不是索引列? 编辑:经过进一步研究我现在意识到,外键只是一个参考工具而不是性能一个,它们也可以(并且应该)被编入索引。但是,索引外键(一个数字)是否比索引短字符串性能更好?
索引标志和其他低基数列通常没有用。例如,如果 table 的一半具有某个标志的特定值,则忽略该标志上的索引并简单地扫描整个 table 会 更快 。
我们确实需要查看查询以判断需要哪些索引。根据您的提示,我还是会刺...
"such as: price range, offer_type, price_period or deal_type" -- 我假设用户会给出最低和最高价格?然后让我们建立一个 "composite" 索引 ending 和 price_per_day
。他们会始终指定所有其他三列吗?每列都有一个值?如果以上都是,那么这个综合指标是最优的:
INDEX(over_types, price_period, deal_type, price_per_day)
(前3列可以任意排列,但应用到范围的东西必须排在最后。)
如果用户可能只包含其中的一些标志,and/or 可能会包含它们的多个值,那么它会变得更加混乱。观察用户的需求并根据常见查询定制额外的索引。使用此 index cookbook 来帮助构建它们。