Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Index hints #9421

Open
2 of 4 tasks
sushantdhiman opened this issue May 9, 2018 · 20 comments
Open
2 of 4 tasks

Index hints #9421

sushantdhiman opened this issue May 9, 2018 · 20 comments
Labels
dialect: mariadb For issues and PRs. Things that involve MariaDB (and do not involve all dialects). dialect: mssql For issues and PRs. Things that involve MSSQL (and do not involve all dialects). dialect: mysql For issues and PRs. Things that involve MySQL (and do not involve all dialects). dialect: sqlite For issues and PRs. Things that involve SQLite (and do not involve all dialects). type: feature For issues and PRs. For new features. Never breaking changes.

Comments

@sushantdhiman
Copy link
Contributor

sushantdhiman commented May 9, 2018

Related support information

Pull requests #9378 , #9409, #8401, #11573

@sushantdhiman sushantdhiman added the type: feature For issues and PRs. For new features. Never breaking changes. label May 9, 2018
@sushantdhiman sushantdhiman added dialect: mssql For issues and PRs. Things that involve MSSQL (and do not involve all dialects). dialect: mysql For issues and PRs. Things that involve MySQL (and do not involve all dialects). dialect: sqlite For issues and PRs. Things that involve SQLite (and do not involve all dialects). labels May 9, 2018
@jessethomson
Copy link

Okay, I think a good starting point might be to go over SQL capabilities, and how/if we want to implement all of these.

Valid MySQL queries:

  1. SELECT * FROM t1 USE INDEX (); Without using indices
  2. SELECT * FROM t1 USE INDEX (i1); With single index
  3. SELECT * FROM t1 USE INDEX (i1,i2); With multiple indices
  4. SELECT * FROM t1 USE INDEX (i1) USE INDEX (i2); With multiple USE INDEX

I think 1, 2, and 3 are all reasonable functionality. I don't see any reason why we would need to implement 4. As far as I know, 4 is simply a syntactically different way to represent 3, without adding any new functionality (I could be wrong).

Note: It is perfectly valid to use the same index more than once in an index hint.
For example:
SELECT * FROM t1 USE INDEX (i1) USE INDEX (i1);
and
SELECT * FROM t1 USE INDEX (i1,i1);
are both valid statement so we don't need to enforce index uniqueness.

@jessethomson
Copy link

jessethomson commented May 17, 2018

Also, it looks like all 3 Pull Requests referenced in the original post are for MySQL. I don't think there is any actual demand for this feature outside of the MySQL dialect; at least nothing that I have been able to find online.

@harbolaez
Copy link

harbolaez commented May 17, 2018

Agree with you @jwt1143 on my PR I was able to pass a collection of indexes. I like option 1, 2 and 3 aswell

SELECT * FROM Order USE INDEX(idx_status_id) WHERE status_id = 1

@harbolaez
Copy link

Also, I like to support the ability to use FORCE INDEX sometimes is useful but rare.

@ezequielzacca
Copy link

is not rare at all for very large databases

@jessethomson
Copy link

jessethomson commented May 18, 2018

Okay. I think it makes sense to support force (and probably ignore too in that case).

Here's an API proposal:

We add an indexHints property to the sequelize options.

db.User.findOne({
    where: {
        email: "joe@example.com",
    },
    indexHints: [
        { type: "use", values: ["i1"] }
    ],
});

Examples:

SELECT * FROM t1 USE INDEX ();

indexHints: [
    { type: "use", values: [] },
]

SELECT * FROM t1 USE INDEX (i1);

indexHints: [
    { type: "use", values: ["i1"] },
]

SELECT * FROM t1 USE INDEX (i1,i2);

indexHints: [
    { type: "use", values: ["i1", "i2"] },
]

SELECT * FROM t1 FORCE INDEX (i1);

indexHints: [
    { type: "force", values: ["i1"] },
]

SELECT * FROM t1 IGNORE INDEX (i1);

indexHints: [
    { type: "force", values: ["i1"] },
]

SELECT * FROM t1 USE INDEX (i1,i2) IGNORE INDEX (i2);

indexHints: [
    { type: "use", values: ["i1","i2"] },
    { type: "ignore", values: ["i2"] },
]

Notes

I prefer using objects over arrays to represent each index hint because they are more explicit.
For example:

indexHints:[
    ["use", ["i1","i2"]]
]

is not nearly as clear as

indexHints: [
    { type: "use", values: ["i1","i2"] },
]

Being more verbose shouldn't be an issue as indexHints are only used in limited/rare circumstances.

@sushantdhiman
Copy link
Contributor Author

@jwt1143 Your proposal looks good, some comments

type should be an constant like query hints

indexHints: [
    { type: IndexHints.USE || FORCE || IGNORE, values: ["i1","i2"] },
]

I also do perfer object based approach

indexHints: [
    { type: IndexHints.USE, values: ["i1","i2"] },
]

As for implementation

MSSQL

We are only going to introduce this

WITH (TableHints, INDEX (<index>))

Form of table hint expansion, we already support table hints for MSSQL, we just need to include index part when indexHints is also supplied, see this pull request

SQLite

Only need to add

INDEXED BY <index_name>

For any given indexHints

MySQL

Up to you, as that is your primary objective with this issue

@monukanyal

This comment has been minimized.

@OsoianMarcel

This comment has been minimized.

@peteychuk

This comment has been minimized.

1 similar comment
@danfarewell

This comment has been minimized.

@KevinTemes

This comment has been minimized.

@Diferno

This comment has been minimized.

@stale

This comment has been minimized.

@stale stale bot added the stale label Jul 23, 2019
@papb papb removed the stale label Jul 24, 2019
@benjamin658
Copy link
Contributor

Will the indexHints option support mariadb dialect?

@papb
Copy link
Member

papb commented Oct 25, 2019

@benjamin658 Thanks for adding it on #11573 :)

@papb papb added the dialect: mariadb For issues and PRs. Things that involve MariaDB (and do not involve all dialects). label Oct 25, 2019
timbowhite pushed a commit to timbowhite/sequelize that referenced this issue Jan 9, 2020
@timbowhite
Copy link

MySQL supports index hints on JOIN statements. It'd be nice to be able to do this:

Project.findAll({
  where: {
    id: {
      [Op.gt]: 623
    },
    name: {
      [Op.like]: 'Foo %'
    }
  },
  include:[{
    association: Company,
    indexHints: [
      {
        type: IndexHints.USE, 
        values: ['index1', 'index2'] 
      }
    ]
  }]
})

and get something like this:

SELECT * FROM Project
INNER JOIN `company` AS `Company` 
  USE INDEX (`index1`,`index2`) 
  ON `Project`.`company_id` = `Company`.`id`
WHERE name LIKE 'FOO %' AND id > 623;

PR incoming.

@theironcook
Copy link

Is it possible to get indexHints enabled with sql server / tedious?

@QuanticPotatoes
Copy link

@timbowhite The index hints on JOIN statements features would be so life saving 🙏

@arafat-al-mahmud
Copy link

Any workaround in v3?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dialect: mariadb For issues and PRs. Things that involve MariaDB (and do not involve all dialects). dialect: mssql For issues and PRs. Things that involve MSSQL (and do not involve all dialects). dialect: mysql For issues and PRs. Things that involve MySQL (and do not involve all dialects). dialect: sqlite For issues and PRs. Things that involve SQLite (and do not involve all dialects). type: feature For issues and PRs. For new features. Never breaking changes.
Projects
None yet
Development

No branches or pull requests